diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt new file mode 100644 index 0000000..57165e6 --- /dev/null +++ b/LICENSES/MIT.txt @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/README.md b/README.md index 374ae0f..d2dc312 100644 --- a/README.md +++ b/README.md @@ -17,3 +17,10 @@ - [Install](http://nginx.org/en/docs/install.html) **nginx** - To configure nginx see [docs/provider-setup.md](docs/provider-setup.md) + +## License + +- csaf_distribution is licensed as Free Software under MIT License. + +- See the specific source files +for details, the license itself can be found in the directory `LICENSES`. \ No newline at end of file diff --git a/cmd/csaf_provider/actions.go b/cmd/csaf_provider/actions.go index b15b660..05a54b3 100644 --- a/cmd/csaf_provider/actions.go +++ b/cmd/csaf_provider/actions.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/config.go b/cmd/csaf_provider/config.go index e81104f..a923721 100644 --- a/cmd/csaf_provider/config.go +++ b/cmd/csaf_provider/config.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/controller.go b/cmd/csaf_provider/controller.go index 24188b1..5ea05f4 100644 --- a/cmd/csaf_provider/controller.go +++ b/cmd/csaf_provider/controller.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/create.go b/cmd/csaf_provider/create.go index 03f0784..78e75e1 100644 --- a/cmd/csaf_provider/create.go +++ b/cmd/csaf_provider/create.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/extract.go b/cmd/csaf_provider/extract.go index 4c8c955..5673cad 100644 --- a/cmd/csaf_provider/extract.go +++ b/cmd/csaf_provider/extract.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/files.go b/cmd/csaf_provider/files.go index 4af9ee9..e29edbd 100644 --- a/cmd/csaf_provider/files.go +++ b/cmd/csaf_provider/files.go @@ -1,19 +1,25 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( - "bytes" "crypto/sha256" "crypto/sha512" "fmt" "hash" - "io" "io/ioutil" "os" ) func writeHash(fname, name string, h hash.Hash, data []byte) error { - if _, err := io.Copy(h, bytes.NewReader(data)); err != nil { + if _, err := h.Write(data); err != nil { return err } diff --git a/cmd/csaf_provider/indices.go b/cmd/csaf_provider/indices.go index f86844b..c9ac116 100644 --- a/cmd/csaf_provider/indices.go +++ b/cmd/csaf_provider/indices.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/main.go b/cmd/csaf_provider/main.go index d4b527a..29a64ec 100644 --- a/cmd/csaf_provider/main.go +++ b/cmd/csaf_provider/main.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/mux.go b/cmd/csaf_provider/mux.go index 12b17ed..34b7e2e 100644 --- a/cmd/csaf_provider/mux.go +++ b/cmd/csaf_provider/mux.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_provider/tmpl/create.html b/cmd/csaf_provider/tmpl/create.html index cdbedc2..74fef6d 100644 --- a/cmd/csaf_provider/tmpl/create.html +++ b/cmd/csaf_provider/tmpl/create.html @@ -1,3 +1,12 @@ + diff --git a/cmd/csaf_provider/tmpl/index.html b/cmd/csaf_provider/tmpl/index.html index de980d0..b9e2be3 100644 --- a/cmd/csaf_provider/tmpl/index.html +++ b/cmd/csaf_provider/tmpl/index.html @@ -1,3 +1,12 @@ + diff --git a/cmd/csaf_provider/tmpl/upload.html b/cmd/csaf_provider/tmpl/upload.html index 4520b49..df718af 100644 --- a/cmd/csaf_provider/tmpl/upload.html +++ b/cmd/csaf_provider/tmpl/upload.html @@ -1,3 +1,12 @@ + diff --git a/cmd/csaf_provider/transaction.go b/cmd/csaf_provider/transaction.go index 936fd0f..6099684 100644 --- a/cmd/csaf_provider/transaction.go +++ b/cmd/csaf_provider/transaction.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( diff --git a/cmd/csaf_uploader/main.go b/cmd/csaf_uploader/main.go index 86a57dd..bd10657 100644 --- a/cmd/csaf_uploader/main.go +++ b/cmd/csaf_uploader/main.go @@ -1,8 +1,17 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package main import ( "bytes" "encoding/json" + "errors" "fmt" "log" "mime/multipart" @@ -11,6 +20,7 @@ import ( "path/filepath" "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/csaf-poc/csaf_distribution/csaf" "github.com/jessevdk/go-flags" "github.com/mitchellh/go-homedir" "golang.org/x/crypto/bcrypt" @@ -18,9 +28,11 @@ import ( ) type options struct { - Action string `short:"a" long:"action" choice:"upload" choice:"create" default:"upload" description:"Action to perform"` - URL string `short:"u" long:"url" description:"URL of the CSAF provider" default:"https://localhost/cgi-bin/csaf_provider.go" value-name:"URL"` - TLP string `short:"t" long:"tlp" choice:"csaf" choice:"white" choice:"green" choice:"amber" choice:"red" default:"csaf" description:"TLP of the feed"` + Action string `short:"a" long:"action" choice:"upload" choice:"create" default:"upload" description:"Action to perform"` + URL string `short:"u" long:"url" description:"URL of the CSAF provider" default:"https://localhost/cgi-bin/csaf_provider.go" value-name:"URL"` + TLP string `short:"t" long:"tlp" choice:"csaf" choice:"white" choice:"green" choice:"amber" choice:"red" default:"csaf" description:"TLP of the feed"` + ExternalSigned bool `short:"x" long:"external-signed" description:"CASF files are signed externally. Assumes .asc files beside CSAF files."` + NoSchemaCheck bool `short:"s" long:"no-schema-check" description:"Do not check files against CSAF JSON schema locally."` Key *string `short:"k" long:"key" description:"OpenPGP key to sign the CSAF files" value-name:"KEY-FILE"` Password *string `short:"p" long:"password" description:"Authentication password for accessing the CSAF provider" value-name:"PASSWORD"` @@ -60,6 +72,9 @@ func newProcessor(opts *options) (*processor, error) { if opts.Action == "upload" { if opts.Key != nil { + if opts.ExternalSigned { + return nil, errors.New("refused to sign external signed files") + } var err error var key *crypto.Key if key, err = loadKey(*opts.Key); err != nil { @@ -89,6 +104,15 @@ func newProcessor(opts *options) (*processor, error) { return &p, nil } +func writeStrings(header string, messages []string) { + if len(messages) > 0 { + fmt.Println(header) + for _, msg := range messages { + fmt.Printf("\t%s\n", msg) + } + } +} + func (p *processor) create() error { req, err := http.NewRequest(http.MethodGet, p.opts.URL+"/api/create", nil) if err != nil { @@ -119,12 +143,8 @@ func (p *processor) create() error { fmt.Printf("\t%s\n", result.Message) } - if len(result.Errors) > 0 { - fmt.Println("Errors:") - for _, err := range result.Errors { - fmt.Printf("\t%s\n", err) - } - } + writeStrings("Errors:", result.Errors) + return nil } @@ -134,6 +154,21 @@ func (p *processor) uploadRequest(filename string) (*http.Request, error) { return nil, err } + if !p.opts.NoSchemaCheck { + var doc interface{} + if err := json.NewDecoder(bytes.NewReader(data)).Decode(&doc); err != nil { + return nil, err + } + errs, err := csaf.ValidateCSAF(doc) + if err != nil { + return nil, err + } + if len(errs) > 0 { + writeStrings("Errors:", errs) + return nil, errors.New("local schema check failed") + } + } + body := new(bytes.Buffer) writer := multipart.NewWriter(body) @@ -170,6 +205,16 @@ func (p *processor) uploadRequest(filename string) (*http.Request, error) { } } + if p.opts.ExternalSigned { + signature, err := os.ReadFile(filename + ".asc") + if err != nil { + return nil, err + } + if err := writer.WriteField("signature", string(signature)); err != nil { + return nil, err + } + } + if err := writer.Close(); err != nil { return nil, err } @@ -220,19 +265,8 @@ func (p *processor) process(filename string) error { fmt.Printf("Release date: %s\n", result.ReleaseDate) } - if len(result.Warnings) > 0 { - fmt.Println("Warnings:") - for _, warning := range result.Warnings { - fmt.Printf("\t%s\n", warning) - } - } - - if len(result.Errors) > 0 { - fmt.Println("Errors:") - for _, err := range result.Errors { - fmt.Printf("\t%s\n", err) - } - } + writeStrings("Warnings:", result.Warnings) + writeStrings("Errors:", result.Errors) return nil } @@ -273,7 +307,7 @@ func checkParser(err error) { if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp { os.Exit(0) } - os.Exit(1) + log.Fatalf("error: %v\n", err) } } @@ -313,6 +347,10 @@ func main() { return } + if len(args) == 0 { + log.Println("No CSAF files given.") + } + for _, arg := range args { check(p.process(arg)) } diff --git a/csaf/models.go b/csaf/models.go index 93544bf..fef4cd3 100644 --- a/csaf/models.go +++ b/csaf/models.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package csaf import ( diff --git a/csaf/rolie.go b/csaf/rolie.go index f1ab9de..12e6beb 100644 --- a/csaf/rolie.go +++ b/csaf/rolie.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package csaf import ( diff --git a/csaf/validation.go b/csaf/validation.go index d753b54..f171234 100644 --- a/csaf/validation.go +++ b/csaf/validation.go @@ -1,3 +1,11 @@ +// This file is Free Software under the MIT License +// without warranty, see README.md and LICENSES/MIT.txt for details. +// +// SPDX-License-Identifier: MIT +// +// SPDX-FileCopyrightText: 2021 German Federal Office for Information Security (BSI) +// Software-Engineering: 2021 Intevation GmbH + package csaf import (