mirror of
https://github.com/netbirdio/netbird.git
synced 2026-03-31 06:34:14 -04:00
95 lines
2.4 KiB
Go
95 lines
2.4 KiB
Go
//go:build unix
|
|
|
|
package cmd
|
|
|
|
import (
|
|
"errors"
|
|
"io"
|
|
"os"
|
|
|
|
"github.com/pkg/sftp"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/spf13/cobra"
|
|
|
|
sshserver "github.com/netbirdio/netbird/client/ssh/server"
|
|
)
|
|
|
|
var (
|
|
sftpUID uint32
|
|
sftpGID uint32
|
|
sftpGroupsInt []uint
|
|
sftpWorkingDir string
|
|
)
|
|
|
|
var sshSftpCmd = &cobra.Command{
|
|
Use: "sftp",
|
|
Short: "SFTP server with privilege dropping (internal use)",
|
|
Hidden: true,
|
|
RunE: sftpMain,
|
|
}
|
|
|
|
func init() {
|
|
sshSftpCmd.Flags().Uint32Var(&sftpUID, "uid", 0, "Target user ID")
|
|
sshSftpCmd.Flags().Uint32Var(&sftpGID, "gid", 0, "Target group ID")
|
|
sshSftpCmd.Flags().UintSliceVar(&sftpGroupsInt, "groups", nil, "Supplementary group IDs (can be repeated)")
|
|
sshSftpCmd.Flags().StringVar(&sftpWorkingDir, "working-dir", "", "Working directory")
|
|
}
|
|
|
|
func sftpMain(cmd *cobra.Command, _ []string) error {
|
|
privilegeDropper := sshserver.NewPrivilegeDropper()
|
|
|
|
var groups []uint32
|
|
for _, groupInt := range sftpGroupsInt {
|
|
groups = append(groups, uint32(groupInt))
|
|
}
|
|
|
|
config := sshserver.ExecutorConfig{
|
|
UID: sftpUID,
|
|
GID: sftpGID,
|
|
Groups: groups,
|
|
WorkingDir: sftpWorkingDir,
|
|
Shell: "",
|
|
Command: "",
|
|
}
|
|
|
|
log.Tracef("dropping privileges for SFTP to UID=%d, GID=%d, groups=%v", config.UID, config.GID, config.Groups)
|
|
|
|
if err := privilegeDropper.DropPrivileges(config.UID, config.GID, config.Groups); err != nil {
|
|
cmd.PrintErrf("privilege drop failed: %v\n", err)
|
|
os.Exit(sshserver.ExitCodePrivilegeDropFail)
|
|
}
|
|
|
|
if config.WorkingDir != "" {
|
|
if err := os.Chdir(config.WorkingDir); err != nil {
|
|
cmd.PrintErrf("failed to change to working directory %s: %v\n", config.WorkingDir, err)
|
|
}
|
|
}
|
|
|
|
sftpServer, err := sftp.NewServer(struct {
|
|
io.Reader
|
|
io.WriteCloser
|
|
}{
|
|
Reader: os.Stdin,
|
|
WriteCloser: os.Stdout,
|
|
})
|
|
if err != nil {
|
|
cmd.PrintErrf("SFTP server creation failed: %v\n", err)
|
|
os.Exit(sshserver.ExitCodeShellExecFail)
|
|
}
|
|
|
|
log.Tracef("starting SFTP server with dropped privileges")
|
|
if err := sftpServer.Serve(); err != nil && !errors.Is(err, io.EOF) {
|
|
cmd.PrintErrf("SFTP server error: %v\n", err)
|
|
if closeErr := sftpServer.Close(); closeErr != nil {
|
|
cmd.PrintErrf("SFTP server close error: %v\n", closeErr)
|
|
}
|
|
os.Exit(sshserver.ExitCodeShellExecFail)
|
|
}
|
|
|
|
if closeErr := sftpServer.Close(); closeErr != nil {
|
|
cmd.PrintErrf("SFTP server close error: %v\n", closeErr)
|
|
}
|
|
os.Exit(sshserver.ExitCodeSuccess)
|
|
return nil
|
|
}
|