Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package go-sendxmpp for openSUSE:Factory checked in at 2026-05-13 17:22:05 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/go-sendxmpp (Old) and /work/SRC/openSUSE:Factory/.go-sendxmpp.new.1966 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "go-sendxmpp" Wed May 13 17:22:05 2026 rev:28 rq:1352929 version:0.15.8 Changes: -------- --- /work/SRC/openSUSE:Factory/go-sendxmpp/go-sendxmpp.changes 2026-05-11 17:07:30.485887741 +0200 +++ /work/SRC/openSUSE:Factory/.go-sendxmpp.new.1966/go-sendxmpp.changes 2026-05-13 17:24:07.227193388 +0200 @@ -1,0 +2,19 @@ +Wed May 13 05:56:48 UTC 2026 - Michael Vetter <[email protected]> + +- Update to 0.15.8: + * Fix windows build (windows doesn't support syscalls Setgid and Setuid). + +------------------------------------------------------------------- +Wed May 13 05:56:31 UTC 2026 - Michael Vetter <[email protected]> + +- Update to 0.15.7: + * Fix http-upload with legacy PGP encryption. + * Fix reading of environment variables. + * Fix a bug in looking up host meta 2. + * Try to drop root privileges before connecting to the server. + * Fix crash if a config key has no value. + * Use a salt for stored FAST token. + * Increase scrypt iterations for storing FAST token from 32768 to 65536. + * Log a warning when --no-tls-verify or -n is set. + +------------------------------------------------------------------- Old: ---- go-sendxmpp-v0.15.6.tar.gz New: ---- go-sendxmpp-v0.15.8.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ go-sendxmpp.spec ++++++ --- /var/tmp/diff_new_pack.MR1b0C/_old 2026-05-13 17:24:08.203233875 +0200 +++ /var/tmp/diff_new_pack.MR1b0C/_new 2026-05-13 17:24:08.207234041 +0200 @@ -17,7 +17,7 @@ Name: go-sendxmpp -Version: 0.15.6 +Version: 0.15.8 Release: 0 Summary: A little tool to send messages to an XMPP contact or MUC License: BSD-2-Clause ++++++ _scmsync.obsinfo ++++++ --- /var/tmp/diff_new_pack.MR1b0C/_old 2026-05-13 17:24:08.267236530 +0200 +++ /var/tmp/diff_new_pack.MR1b0C/_new 2026-05-13 17:24:08.271236696 +0200 @@ -1,6 +1,6 @@ -mtime: 1778446715 -commit: 3233426c4d6842ae364d02186066d3b69096428759de00e5ab0bd0a3c917d2e7 +mtime: 1778651892 +commit: 15e740b0889cf05bf7051482dafc10882cf35eff3337bc71f45a16de950180b2 url: https://src.opensuse.org/xmpp/go-sendxmpp -revision: 3233426c4d6842ae364d02186066d3b69096428759de00e5ab0bd0a3c917d2e7 +revision: 15e740b0889cf05bf7051482dafc10882cf35eff3337bc71f45a16de950180b2 projectscmsync: https://src.opensuse.org/xmpp/_ObsPrj.git ++++++ build.specials.obscpio ++++++ ++++++ build.specials.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/.gitignore new/.gitignore --- old/.gitignore 1970-01-01 01:00:00.000000000 +0100 +++ new/.gitignore 2026-05-13 07:58:12.000000000 +0200 @@ -0,0 +1 @@ +.osc ++++++ go-sendxmpp-v0.15.6.tar.gz -> go-sendxmpp-v0.15.8.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/.gitlab-ci.yml new/go-sendxmpp-v0.15.8/.gitlab-ci.yml --- old/go-sendxmpp-v0.15.6/.gitlab-ci.yml 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/.gitlab-ci.yml 2026-05-12 19:59:13.000000000 +0200 @@ -26,7 +26,7 @@ - build - release -format: +format_and_static_test: # image: registry.gitlab.com/gitlab-org/gitlab-build-images:golangci-lint-alpine stage: test before_script: @@ -34,12 +34,14 @@ - echo "deb https://deb.debian.org/debian/ $DEB_RELEASE-backports main" >> /etc/apt/sources.list - apt -qq update; apt -qq install -y codespell - go install mvdan.cc/gofumpt@latest + - go install github.com/securego/gosec/v2/cmd/gosec@latest script: - go fmt $(go list ./... | grep -v /vendor/) - go vet $(go list ./... | grep -v /vendor/) - go test -race $(go list ./... | grep -v /vendor/) - codespell *.go *.md man/*.ronn - gofumpt -d . + - gosec ./... # Taken from https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20404/diffs#diff-content-8071267ea32ba69f24a8bd50bcbddf972c295ce3 # Use default .golangci.yml file from the image if one is not present in the project root. #- '[ -e .golangci.yml ] || cp /golangci/.golangci.yml .' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/CHANGELOG.md new/go-sendxmpp-v0.15.8/CHANGELOG.md --- old/go-sendxmpp-v0.15.6/CHANGELOG.md 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/CHANGELOG.md 2026-05-12 19:59:13.000000000 +0200 @@ -1,4 +1,19 @@ # Changelog +## [v0.15.8] 2026-05-12 +### Changed +- Fix windows build (windows doesn't support syscalls Setgid and Setuid). + +## [v0.15.7] 2026-05-12 +### Changed +- Fix http-upload with legacy PGP encryption. +- Fix reading of environment variables. +- Fix a bug in looking up host meta 2. +- Try to drop root privileges before connecting to the server. +- Fix crash if a config key has no value. +- Use a salt for stored FAST token. +- Increase scrypt iterations for storing FAST token from 32768 to 65536. +- Log a warning when `--no-tls-verify` or `-n` is set. + ## [v0.15.6] 2026-05-01 ### Added - New config option `allow_plain`. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/authpinning.go new/go-sendxmpp-v0.15.8/authpinning.go --- old/go-sendxmpp-v0.15.6/authpinning.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/authpinning.go 2026-05-12 19:59:13.000000000 +0200 @@ -24,6 +24,7 @@ } // Read file. slog.Info("reading auth pin", "file", authPinFile) + // #nosec G304 -- auth pin file comes from the local system, it's no untrusted input from the network f, err := os.ReadFile(authPinFile) if err != nil { return false, fmt.Errorf("parse auth pin file: %w", err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/connect.go new/go-sendxmpp-v0.15.8/connect.go --- old/go-sendxmpp-v0.15.6/connect.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/connect.go 2026-05-12 19:59:13.000000000 +0200 @@ -80,7 +80,7 @@ // Look up hostmeta2 file. slog.Info("looking up host meta 2 for", "server", server) hm2, httpStatus, err := xmppsrv.LookupHostmeta2(serverASCII) - if httpStatus != 404 && err != nil { + if httpStatus != 404 && err == nil { for _, link := range hm2.Links { if link.Rel == nsC2SdTLS { options.NoTLS = false diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/const.go new/go-sendxmpp-v0.15.8/const.go --- old/go-sendxmpp-v0.15.6/const.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/const.go 2026-05-12 19:59:13.000000000 +0200 @@ -5,7 +5,7 @@ package main const ( - version = "0.15.6" + version = "0.15.8" // defaults defaultBufferSize = 100 defaultConfigColumnSep = 2 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/dropprivs_unix.go new/go-sendxmpp-v0.15.8/dropprivs_unix.go --- old/go-sendxmpp-v0.15.6/dropprivs_unix.go 1970-01-01 01:00:00.000000000 +0100 +++ new/go-sendxmpp-v0.15.8/dropprivs_unix.go 2026-05-12 19:59:13.000000000 +0200 @@ -0,0 +1,45 @@ +// Copyright Martin Dosch. +// Use of this source code is governed by the BSD-2-clause +// license that can be found in the LICENSE file. +//go:build !windows + +package main + +import ( + "fmt" + "log/slog" + osUser "os/user" + "strconv" + "syscall" +) + +func dropPrivs() error { + slog.Info("Trying to drop root privileges before connecting to the server") + nobody, err := osUser.Lookup("nobody") + if err != nil { + slog.Info("failed to look up user nobody, will not drop privileges") + return fmt.Errorf("failed to drop root privilege: %w", err) + } else { + gid, err := strconv.Atoi(nobody.Gid) + if err != nil { + return fmt.Errorf("failed to drop root privilege: %w", err) + } + uid, err := strconv.Atoi(nobody.Uid) + if err != nil { + return fmt.Errorf("failed to drop root privilege: %w", err) + } + err = syscall.Setgid(gid) + if err != nil { + slog.Info("failed to drop privileges to user nobody", "GID", gid) + return fmt.Errorf("failed to drop root privilege: %w", err) + } + err = syscall.Setuid(uid) + if err != nil { + slog.Info("failed to drop privileges to user nobody", "UID", uid) + return fmt.Errorf("failed to drop root privilege: %w", err) + } + } + slog.Info("user identification", "UID", syscall.Getuid()) + slog.Info("user identification", "GID", syscall.Getgid()) + return nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/dropprivs_windows.go new/go-sendxmpp-v0.15.8/dropprivs_windows.go --- old/go-sendxmpp-v0.15.6/dropprivs_windows.go 1970-01-01 01:00:00.000000000 +0100 +++ new/go-sendxmpp-v0.15.8/dropprivs_windows.go 2026-05-12 19:59:13.000000000 +0200 @@ -0,0 +1,11 @@ +// Copyright Martin Dosch. +// Use of this source code is governed by the BSD-2-clause +// license that can be found in the LICENSE file. +//go:build windows + +package main + +func dropPrivs() error { + // Windows doesn't support syscall.Setuid and syscall.Setgid + return nil +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/go.mod new/go-sendxmpp-v0.15.8/go.mod --- old/go-sendxmpp-v0.15.6/go.mod 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/go.mod 2026-05-12 19:59:13.000000000 +0200 @@ -9,14 +9,14 @@ github.com/google/uuid v1.6.0 github.com/pborman/getopt/v2 v2.1.0 github.com/xmppo/go-xmpp v0.3.4 - golang.org/x/crypto v0.50.0 - golang.org/x/net v0.53.0 + golang.org/x/crypto v0.51.0 + golang.org/x/net v0.54.0 salsa.debian.org/mdosch/xmppsrv v0.3.3 ) require ( github.com/ProtonMail/go-crypto v1.4.1 // indirect github.com/cloudflare/circl v1.6.3 // indirect - golang.org/x/sys v0.43.0 // indirect - golang.org/x/text v0.36.0 // indirect + golang.org/x/sys v0.44.0 // indirect + golang.org/x/text v0.37.0 // indirect ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/go.sum new/go-sendxmpp-v0.15.8/go.sum --- old/go-sendxmpp-v0.15.6/go.sum 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/go.sum 2026-05-12 19:59:13.000000000 +0200 @@ -20,14 +20,14 @@ github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/xmppo/go-xmpp v0.3.4 h1:w7EBGsEzz2TBGJ2FQcOEn0CDzkuJ9CpUBIA+oJB5EuE= github.com/xmppo/go-xmpp v0.3.4/go.mod h1:03Za3Szic72CqdDIdlZtnay9R7t2MWJsj6ZpCvxlGDs= -golang.org/x/crypto v0.50.0 h1:zO47/JPrL6vsNkINmLoo/PH1gcxpls50DNogFvB5ZGI= -golang.org/x/crypto v0.50.0/go.mod h1:3muZ7vA7PBCE6xgPX7nkzzjiUq87kRItoJQM1Yo8S+Q= -golang.org/x/net v0.53.0 h1:d+qAbo5L0orcWAr0a9JweQpjXF19LMXJE8Ey7hwOdUA= -golang.org/x/net v0.53.0/go.mod h1:JvMuJH7rrdiCfbeHoo3fCQU24Lf5JJwT9W3sJFulfgs= -golang.org/x/sys v0.43.0 h1:Rlag2XtaFTxp19wS8MXlJwTvoh8ArU6ezoyFsMyCTNI= -golang.org/x/sys v0.43.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= -golang.org/x/text v0.36.0 h1:JfKh3XmcRPqZPKevfXVpI1wXPTqbkE5f7JA92a55Yxg= -golang.org/x/text v0.36.0/go.mod h1:NIdBknypM8iqVmPiuco0Dh6P5Jcdk8lJL0CUebqK164= +golang.org/x/crypto v0.51.0 h1:IBPXwPfKxY7cWQZ38ZCIRPI50YLeevDLlLnyC5wRGTI= +golang.org/x/crypto v0.51.0/go.mod h1:8AdwkbraGNABw2kOX6YFPs3WM22XqI4EXEd8g+x7Oc8= +golang.org/x/net v0.54.0 h1:2zJIZAxAHV/OHCDTCOHAYehQzLfSXuf/5SoL/Dv6w/w= +golang.org/x/net v0.54.0/go.mod h1:Sj4oj8jK6XmHpBZU/zWHw3BV3abl4Kvi+Ut7cQcY+cQ= +golang.org/x/sys v0.44.0 h1:ildZl3J4uzeKP07r2F++Op7E9B29JRUy+a27EibtBTQ= +golang.org/x/sys v0.44.0/go.mod h1:4GL1E5IUh+htKOUEOaiffhrAeqysfVGipDYzABqnCmw= +golang.org/x/text v0.37.0 h1:Cqjiwd9eSg8e0QAkyCaQTNHFIIzWtidPahFWR83rTrc= +golang.org/x/text v0.37.0/go.mod h1:a5sjxXGs9hsn/AJVwuElvCAo9v8QYLzvavO5z2PiM38= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= salsa.debian.org/mdosch/xmppsrv v0.3.3 h1:F8FGyw1Q1LkAs/UbIXd6Obd33q2CKWrIxxrzvuLSVuM= diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/helpers.go new/go-sendxmpp-v0.15.8/helpers.go --- old/go-sendxmpp-v0.15.6/helpers.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/helpers.go 2026-05-12 19:59:13.000000000 +0200 @@ -51,11 +51,17 @@ } func readFile(path string) (*bytes.Buffer, error) { + // #nosec G304 -- path comes from the local system, it's no untrusted input from the network file, err := os.Open(path) if err != nil { return nil, fmt.Errorf("read file: %w", err) } - defer file.Close() + defer func() { + derr := file.Close() + if derr != nil { + slog.Warn("closing file failed", "error", derr) + } + }() buffer := new(bytes.Buffer) _, err = buffer.ReadFrom(file) if err != nil { @@ -64,7 +70,7 @@ return buffer, nil } -func getFastData(jid string, password string) (xmpp.Fast, error) { +func getFastData(jid string, password string, clientID string) (xmpp.Fast, error) { folder := fsFriendlyJid(jid) var fast xmpp.Fast fastPath, err := getDataPath(folder, true) @@ -83,8 +89,8 @@ if err != nil { return xmpp.Fast{}, fmt.Errorf("get fast data: failed to read fast cache file: %w", err) } - salt := make([]byte, 32) - key, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) + salt := []byte(clientID) + key, err := scrypt.Key([]byte(password), salt, 65536, 8, 1, 32) if err != nil { return xmpp.Fast{}, fmt.Errorf("get fast data: failed to create aes key: %w", err) } @@ -118,7 +124,7 @@ return os.Remove(fastFileLoc) } -func writeFastData(jid string, password string, fast xmpp.Fast) error { +func writeFastData(jid string, password string, clientID string, fast xmpp.Fast) error { var encBuf bytes.Buffer folder := fsFriendlyJid(jid) fastPath, err := getDataPath(folder, true) @@ -127,8 +133,8 @@ } fastFileLoc := fastPath + "fast.bin" slog.Info("writing FAST data:", "file", fastFileLoc) - salt := make([]byte, 32) - key, err := scrypt.Key([]byte(password), salt, 32768, 8, 1, 32) + salt := []byte(clientID) + key, err := scrypt.Key([]byte(password), salt, 65536, 8, 1, 32) if err != nil { return fmt.Errorf("write fast data: failed to create aes cipher: %w", err) } @@ -152,11 +158,17 @@ if err != nil { return fmt.Errorf("write fast data: failed to create fast token file: %w", err) } + // #nosec G304 -- fast file loc comes from the local system, it's no untrusted input from the network file, err := os.Create(fastFileLoc) if err != nil { return fmt.Errorf("write fast data: failed to create fast token file: %w", err) } - defer file.Close() + defer func() { + derr := file.Close() + if derr != nil { + slog.Warn("closing file failed", "error", derr) + } + }() if runtime.GOOS != "windows" { _ = file.Chmod(os.FileMode(defaultFileRights)) } else { @@ -179,11 +191,18 @@ buf, err := readFile(clientIDLoc) if err != nil { clientID = uuid.NewString() + // #nosec G304 -- client ID location comes from the local system, + // it's no untrusted input from the network file, err := os.Create(clientIDLoc) if err != nil { return strEmpty, fmt.Errorf("get client id: failed to create clientid file: %w", err) } - defer file.Close() + defer func() { + derr := file.Close() + if derr != nil { + slog.Warn("closing file failed", "error", derr) + } + }() if runtime.GOOS != "windows" { _ = file.Chmod(os.FileMode(defaultFileRights)) } else { @@ -203,15 +222,15 @@ var err error var homeDir, dataDir string switch { - case os.Getenv("$XDG_DATA_HOME") != "": - dataDir = os.Getenv("$XDG_DATA_HOME") + case os.Getenv("XDG_DATA_HOME") != "": + dataDir = os.Getenv("XDG_DATA_HOME") slog.Info("using", "XDG_DATA_HOME", dataDir) - case os.Getenv("$XDG_HOME") != "": - homeDir = os.Getenv("$XDG_HOME") + case os.Getenv("XDG_HOME") != "": + homeDir = os.Getenv("XDG_HOME") slog.Info("using", "XDG_HOME", homeDir) dataDir = homeDir + "/.local/share" - case os.Getenv("$HOME") != "": - homeDir = os.Getenv("$HOME") + case os.Getenv("HOME") != "": + homeDir = os.Getenv("HOME") slog.Info("using", "HOME", homeDir) dataDir = homeDir + "/.local/share" default: @@ -230,8 +249,10 @@ } dataDir = fmt.Sprintf("%s/go-sendxmpp/%s", dataDir, folder) slog.Info("using data", "dir", dataDir) + // #nosec G703 -- data dir comes from the local system, it's no untrusted input from the network _, err = os.Stat(dataDir) if create && os.IsNotExist(err) { + // #nosec G703 -- data dir comes from the local system, it's no untrusted input from the network err = os.MkdirAll(dataDir, defaultDirRights) if err != nil { return strError, fmt.Errorf("get data path: could not create folder: %w", err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/httpupload.go new/go-sendxmpp-v0.15.8/httpupload.go --- old/go-sendxmpp-v0.15.6/httpupload.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/httpupload.go 2026-05-12 19:59:13.000000000 +0200 @@ -87,14 +87,18 @@ } for _, filePath := range filePaths { // Read file + // #nosec G304 -- file path is supplied by the user, it's no untrusted input from the network file, err := os.Open(filePath) if err != nil { return urls, fmt.Errorf("http-upload: read file: %w", err) } - defer file.Close() fileStat, err := file.Stat() if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: stat file: %w", err) } fileSize := fileStat.Size() @@ -102,6 +106,10 @@ // Get mime type mtype, err := mimetype.DetectFile(filePath) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: detect mimetype: %w", err) } mimeType := mtype.String() @@ -109,12 +117,20 @@ var mimeTypeEscaped bytes.Buffer xml.Escape(&mimeTypeEscaped, []byte(mimeType)) if oxPrivKey != nil { - _, err = readFile(filePath) + buf, err := readFile(filePath) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return nil, fmt.Errorf("http-upload: %w", err) } - buffer, err = legacyPGPEncryptFile(oxPrivKey, keyRing, buffer) + buffer, err = legacyPGPEncryptFile(oxPrivKey, keyRing, buf) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } fileSize = int64(buffer.Len()) @@ -136,6 +152,10 @@ // the best. if maxFileSize != 0 { if int64(fileSize) > maxFileSize { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: file size %s MiB is larger than the maximum file size allowed (%s MiB)", strconv.FormatInt(int64(fileSize)/1024/1024, 10), strconv.FormatInt(maxFileSize/1024/1024, 10)) } @@ -150,6 +170,10 @@ requestReq.CreateAttr("content-type", mimeType) r, err := request.WriteToString() if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } @@ -157,9 +181,17 @@ slog.Info("http-upload: requesting upload slot") uploadSlot, err := getSlot(client, slc, uploadComponent, r) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } if !strings.HasPrefix(uploadSlot.Put.Url, "https://") { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: upload slot does not provide https") } // Upload file @@ -173,6 +205,10 @@ if proxyEnv != "" { proxyURL, err := url.Parse(proxyEnv) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } slog.Info("http-upload: using http transport", "proxy", proxyURL) @@ -185,6 +221,10 @@ req, err = http.NewRequest(http.MethodPut, uploadSlot.Put.Url, file) } if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } req.ContentLength = fileSize @@ -200,19 +240,35 @@ } resp, err := httpClient.Do(req) if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, err } slog.Info("http-upload: received http", "status", resp.StatusCode) // Test for http status code "200 OK" or "201 Created" if resp.StatusCode != 200 && resp.StatusCode != 201 { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: upload failed") } // Return http link if uploadSlot.Get.Url == strEmpty { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: no url attribute") } if !strings.HasPrefix(uploadSlot.Get.Url, "https://") { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err2) + } return urls, fmt.Errorf("http-upload: get url does not provide https") } slog.Info("http-upload: received get", "URL", uploadSlot.Get.Url) @@ -221,7 +277,10 @@ fmt.Println("http-upload: error while closing http request body:", err) } urls = append(urls, uploadSlot.Get.Url) - file.Close() + err = file.Close() + if err != nil { + slog.Warn("closing file failed", "error", err) + } } return urls, nil } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/main.go new/go-sendxmpp-v0.15.8/main.go --- old/go-sendxmpp-v0.15.6/main.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/main.go 2026-05-12 19:59:13.000000000 +0200 @@ -18,6 +18,7 @@ osUser "os/user" "runtime" "strings" + "syscall" "time" gopenpgpConst "github.com/ProtonMail/gopenpgp/v3/constants" // MIT License @@ -60,11 +61,17 @@ // Open message file. slog.Info("opening file", "file", filePath) + // #nosec G304 -- file path is supplied by the user, it's no untrusted input from the network file, err := os.Open(filePath) if err != nil { return output, fmt.Errorf("read file by line: %w", err) } - defer file.Close() + defer func() { + derr := file.Close() + if derr != nil { + slog.Warn("closing file failed", "error", derr) + } + }() scanner := bufio.NewScanner(file) scanner.Split(bufio.ScanLines) for scanner.Scan() { @@ -93,7 +100,7 @@ var ( err error message, user, server, password, alias string - allowPLAIN bool + allowPLAIN, isRoot bool oxPrivKey *crypto.Key recipients []recipientsType fast xmpp.Fast @@ -105,6 +112,7 @@ log.SetFlags(0) log.SetOutput(new(prettyLogger)) + slog.SetLogLoggerLevel(slog.LevelWarn) // Define command line flags. flagHelp := getopt.BoolLong("help", 0, "Show help.") flagHTTPUpload := getopt.ListLong("http-upload", 'h', "Send a file via http-upload. Can be invoked several times to upload multiple files.") @@ -202,8 +210,8 @@ log.Fatal("Specifying a username is required when using anonymous authentication.") } - if !*flagVerbose { - slog.SetLogLoggerLevel(slog.LevelError) + if *flagVerbose { + slog.SetLogLoggerLevel(slog.LevelDebug) } // Print a warning if go-sendxmpp is run by the user root on non-windows systems. @@ -215,12 +223,20 @@ log.Fatal("Failed to get current user: ", err) } slog.Info("checking if OS user is root") + slog.Info("user identification", "UID", syscall.Getuid()) + slog.Info("user identification", "GID", syscall.Getgid()) if currUser.Username == "root" { fmt.Println("WARNING: It seems you are running go-sendxmpp as root user.\n" + "This is not recommended as go-sendxmpp does not require root " + "privileges. Please consider using a less privileged user. For an " + "example how to do this with sudo please consult the manpage chapter " + "TIPS.") + // Logging that we're running as root + isRoot = true + *flagFastOff = true + slog.Info("disabling fast as we're running as root") + *flagOx = false + slog.Info("disabling OX as we're running as root") } } @@ -346,7 +362,10 @@ if !*flagFastOff { slog.Info("getting FAST data") - fast, _ = getFastData(user, password) + fast, err = getFastData(user, password, clientID) + if err != nil { + slog.Info("no FAST data found") + } // Reset FAST token and mechanism if expired or // FastInvalidate is set. if time.Now().After(fast.Expiry) || *flagFastInvalidate { @@ -357,7 +376,7 @@ } } if fast.Mechanism != "" && *flagSCRAMPinning != "" { - log.Fatalf(("FAST: %s is requested, but we have a token for %s."), *flagSCRAMPinning, fast.Mechanism) + log.Fatalf("FAST: %s is requested, but we have a token for %s.", *flagSCRAMPinning, fast.Mechanism) } var tlsConfig tls.Config @@ -380,8 +399,13 @@ // Use ALPN tlsConfig.NextProtos = append(tlsConfig.NextProtos, "xmpp-client") slog.Info("setting TLS config:", "NextProtos", tlsConfig.NextProtos) - tlsConfig.InsecureSkipVerify = *flagSkipVerify - slog.Info("setting TLS config:", "InsecureSkipVerify", tlsConfig.InsecureSkipVerify) + if *flagSkipVerify { + // #nosec G402 -- user must explicitly enable it and a warning is logged + tlsConfig.InsecureSkipVerify = *flagSkipVerify + slog.Warn("TLS config INSECURE:", "InsecureSkipVerify", tlsConfig.InsecureSkipVerify) + } else { + slog.Info("setting TLS config:", "InsecureSkipVerify", tlsConfig.InsecureSkipVerify) + } tlsConfig.Renegotiation = tls.RenegotiateNever slog.Info("setting TLS config:", "Renegotiation", tlsConfig.Renegotiation) switch *flagTLSMinVersion { @@ -514,6 +538,10 @@ os.Exit(0) } + if isRoot { + _ = dropPrivs() + } + // Connect to server. client, err := connect(options, *flagDirectTLS, *flagAnon, *flagRetryConnect, *flagRetryConnectMax) if err != nil { @@ -541,7 +569,7 @@ fast.Expiry = client.Fast.Expiry slog.Info("updating FAST:", "expiry", fast.Expiry) slog.Info("writing FAST data to disk") - err := writeFastData(user, password, fast) + err := writeFastData(user, password, clientID, fast) if err != nil { fmt.Println(err) } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1 new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1 --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1 2026-05-12 19:59:13.000000000 +0200 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "GO\-SENDXMPP" "1" "April 2026" "" +.TH "GO\-SENDXMPP" "1" "May 2026" "" .SH "NAME" \fBgo\-sendxmpp\fR \- A tool to send messages to an XMPP contact or MUC\. .SH "SYNOPSIS" @@ -164,6 +164,8 @@ # command\-that\-requires\-root|sudo \-H \-u sendxmpp go\-sendxmpp me@example\.org .fi .IP "" 0 +.P +If go\-sendxmpp is run as root it will drop the root privileges before connecting to the server\. This means \fBFAST\fR and \fBOX\fR will be disabled as go\-sendxmpp will not have the necessary rights to store the necessary data (e\.g\. FAST tokes or OX key material) after dropping the privileges\. This is just to avoid network connections as root and doesn't mean that running as root as a supported use case, in fact it is highly recommended to never run go\-sendxmpp as root\. .SH "SHELL COMPLETIONS" .SS "ZSH" There are no shell completions yet (contributions welcome) but for zsh it is possible to automatically create completions from \fB\-\-help\fR which might work good enough\. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1.html new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1.html --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1.html 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1.html 2026-05-12 19:59:13.000000000 +0200 @@ -278,6 +278,12 @@ <pre><code># command-that-requires-root|sudo -H -u sendxmpp go-sendxmpp [email protected] </code></pre> +<p>If go-sendxmpp is run as root it will drop the root privileges before connecting to the server. +This means <strong>FAST</strong> and <strong>OX</strong> will be disabled as go-sendxmpp will not have the necessary rights to store +the necessary data (e.g. FAST tokes or OX key material) after dropping the privileges. +This is just to avoid network connections as root and doesn't mean that running as root as a supported use case, +in fact it is highly recommended to never run go-sendxmpp as root.</p> + <h2 id="SHELL-COMPLETIONS">SHELL COMPLETIONS</h2> <h3 id="ZSH">ZSH</h3> @@ -317,11 +323,11 @@ <h2 id="SEE-ALSO">SEE ALSO</h2> -<p><a class="man-ref" href="go-sendxmpp.5.html">go-sendxmpp<span class="s">(5)</span></a>, <span class="man-ref">xmppc<span class="s">(1)</span></span>, <span class="man-ref">sendxmpp<span class="s">(1)</span></span></p> +<p><span class="man-ref">go-sendxmpp<span class="s">(5)</span></span>, <span class="man-ref">xmppc<span class="s">(1)</span></span>, <span class="man-ref">sendxmpp<span class="s">(1)</span></span></p> <ol class='man-decor man-foot man foot'> <li class='tl'></li> - <li class='tc'>April 2026</li> + <li class='tc'>May 2026</li> <li class='tr'>go-sendxmpp(1)</li> </ol> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1.ronn new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1.ronn --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.1.ronn 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.1.ronn 2026-05-12 19:59:13.000000000 +0200 @@ -210,6 +210,12 @@ # command-that-requires-root|sudo -H -u sendxmpp go-sendxmpp [email protected] ``` +If go-sendxmpp is run as root it will drop the root privileges before connecting to the server. +This means **FAST** and **OX** will be disabled as go-sendxmpp will not have the necessary rights to store +the necessary data (e.g. FAST tokes or OX key material) after dropping the privileges. +This is just to avoid network connections as root and doesn't mean that running as root as a supported use case, +in fact it is highly recommended to never run go-sendxmpp as root. + ## SHELL COMPLETIONS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5 new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5 --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5 2026-05-12 19:59:13.000000000 +0200 @@ -1,6 +1,6 @@ .\" generated with Ronn-NG/v0.10.1 .\" http://github.com/apjanke/ronn-ng/tree/0.10.1 -.TH "GO\-SENDXMPP" "5" "April 2026" "" +.TH "GO\-SENDXMPP" "5" "May 2026" "" .SH "NAME" \fBgo\-sendxmpp\fR \- A tool to send messages to an XMPP contact or MUC\. .SH "LOCATION" @@ -16,7 +16,9 @@ .br eval_password: [\fIcommand_to_unlock_your_password\fR] .br -alias: [\fIyour_alias\fR] allow_plain: [\fIbool\fR] +alias: [\fIyour_alias\fR] +.br +allow_plain: [\fIbool\fR] .SH "REQUIRED SETTINGS" If all necessary settings are supplied as command line arguments no config file is needed at all\. Setting \fBjserver\fR and \fBport\fR might not be necessary depending on the used server\. .br diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5.html new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5.html --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5.html 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5.html 2026-05-12 19:59:13.000000000 +0200 @@ -89,7 +89,7 @@ port: [<var>jabber_port</var>] <br> password: [<var>your_jabber_password</var>] <br> eval_password: [<var>command_to_unlock_your_password</var>] <br> -alias: [<var>your_alias</var>] +alias: [<var>your_alias</var>] <br> allow_plain: [<var>bool</var>]</p> <h2 id="REQUIRED-SETTINGS">REQUIRED SETTINGS</h2> @@ -140,11 +140,11 @@ <h2 id="SEE-ALSO">SEE ALSO</h2> -<p><a class="man-ref" href="go-sendxmpp.1.html">go-sendxmpp<span class="s">(1)</span></a>, <span class="man-ref">sendxmpp<span class="s">(1)</span></span></p> +<p><span class="man-ref">go-sendxmpp<span class="s">(1)</span></span>, <span class="man-ref">sendxmpp<span class="s">(1)</span></span></p> <ol class='man-decor man-foot man foot'> <li class='tl'></li> - <li class='tc'>April 2026</li> + <li class='tc'>May 2026</li> <li class='tr'>go-sendxmpp(5)</li> </ol> diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5.ronn new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5.ronn --- old/go-sendxmpp-v0.15.6/man/go-sendxmpp.5.ronn 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/man/go-sendxmpp.5.ronn 2026-05-12 19:59:13.000000000 +0200 @@ -14,7 +14,7 @@ port: [<jabber_port>] password: [<your_jabber_password>] eval_password: [<command_to_unlock_your_password>] -alias: [<your_alias>] +alias: [<your_alias>] allow_plain: [<bool>] ## REQUIRED SETTINGS diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/ox.go new/go-sendxmpp-v0.15.8/ox.go --- old/go-sendxmpp-v0.15.6/ox.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/ox.go 2026-05-12 19:59:13.000000000 +0200 @@ -419,6 +419,7 @@ return dataFile, err } } + // #nosec G304 -- old data dir comes from the local system, it's no untrusted input from the network dir, err := os.Open(oldDataDir) if err == nil { slog.Info("ox: get private key location: entering old data", "folder", oldDataDir) @@ -492,6 +493,7 @@ func oxStoreKey(location string, key string) error { var file *os.File slog.Info("ox: storing key:", "location", location) + // #nosec G304 -- location comes from the local system, it's no untrusted input from the network file, err := os.Create(location) if err != nil { return fmt.Errorf("ox: store key: failed to create key location: %w", err) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/go-sendxmpp-v0.15.6/parseconfig.go new/go-sendxmpp-v0.15.8/parseconfig.go --- old/go-sendxmpp-v0.15.6/parseconfig.go 2026-05-01 11:42:03.000000000 +0200 +++ new/go-sendxmpp-v0.15.8/parseconfig.go 2026-05-12 19:59:13.000000000 +0200 @@ -9,6 +9,7 @@ "bufio" "fmt" "log" + "log/slog" "os" "os/exec" "os/user" @@ -28,7 +29,7 @@ if home == "" { return "", fmt.Errorf("find config: no home directory found") } - osConfigDir := os.Getenv("$XDG_CONFIG_HOME") + osConfigDir := os.Getenv("XDG_CONFIG_HOME") if osConfigDir == "" { osConfigDir = home + "/.config" } @@ -77,6 +78,7 @@ } // Open config file. + // #nosec G304 -- config path comes from the local system, it's no untrusted input from the network file, err := os.Open(configPath) if err != nil { return output, fmt.Errorf("parse config: failed to open config file: %w", err) @@ -92,54 +94,61 @@ column := strings.SplitN(scanner.Text(), " ", defaultConfigColumnSep) - switch column[0] { - case "username:": - output.username = column[1] - case "jserver:": - output.jserver = column[1] - case "password:": - output.password = column[1] - case "eval_password:": - shell := os.Getenv("SHELL") - if shell == "" { - shell = "/bin/sh" - } - out, err := exec.Command(shell, "-c", column[1]).Output() - if err != nil { - file.Close() - log.Fatal(err) - } - output.password = string(out) - if output.password[len(output.password)-1] == '\n' { - output.password = output.password[:len(output.password)-1] - } - case "port:": - output.port = column[1] - case "alias:": - output.alias = column[1] - case "allow_plain:": - if strings.ToLower(column[1]) == "true" { - output.allowPLAIN = true - } else { - output.allowPLAIN = false - } - default: - // Try to parse legacy sendxmpp config files. - if len(column) >= defaultConfigColumnSep && strings.Contains(column[0], "@") { - if strings.Contains(scanner.Text(), ";") { - output.username = strings.Split(column[0], ";")[0] - output.jserver = strings.Split(column[0], ";")[1] - output.password = column[1] + if len(column) > 1 { + switch column[0] { + case "username:": + output.username = column[1] + case "jserver:": + output.jserver = column[1] + case "password:": + output.password = column[1] + case "eval_password:": + shell := os.Getenv("SHELL") + if shell == "" { + shell = "/bin/sh" + } + // #nosec G204,G702 -- command to unlock password manager is supplied by the user + // in the config and no untrusted data + out, err := exec.Command(shell, "-c", column[1]).Output() + if err != nil { + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err) + } + log.Fatal(err) + } + output.password = string(out) + if output.password[len(output.password)-1] == '\n' { + output.password = output.password[:len(output.password)-1] + } + case "port:": + output.port = column[1] + case "alias:": + output.alias = column[1] + case "allow_plain:": + if strings.ToLower(column[1]) == "true" { + output.allowPLAIN = true } else { - output.username = strings.Split(column[0], ":")[0] - if strings.Contains(output.username, "@") { - jserver := strings.SplitAfter(output.username, "@")[1] - if len(jserver) < defaultLenServerConf { - log.Fatal("Couldn't parse config: ", column[0]) + output.allowPLAIN = false + } + default: + // Try to parse legacy sendxmpp config files. + if len(column) >= defaultConfigColumnSep && strings.Contains(column[0], "@") { + if strings.Contains(scanner.Text(), ";") { + output.username = strings.Split(column[0], ";")[0] + output.jserver = strings.Split(column[0], ";")[1] + output.password = column[1] + } else { + output.username = strings.Split(column[0], ":")[0] + if strings.Contains(output.username, "@") { + jserver := strings.SplitAfter(output.username, "@")[1] + if len(jserver) < defaultLenServerConf { + log.Fatal("Couldn't parse config: ", column[0]) + } + output.jserver = jserver } - output.jserver = jserver + output.password = column[1] } - output.password = column[1] } } } @@ -158,6 +167,9 @@ } } - file.Close() + err2 := file.Close() + if err2 != nil { + slog.Warn("closing file failed", "error", err) + } return output, err } ++++++ vendor.tar.zst ++++++ ++++ 31542 lines of diff (skipped)
