diff --git a/cmd/grumble/args.go b/cmd/grumble/args.go index 816c196..e0cbd7d 100644 --- a/cmd/grumble/args.go +++ b/cmd/grumble/args.go @@ -21,7 +21,7 @@ var usageTmpl = `usage: grumble [options] grumble {{.Version}} ({{.BuildDate}}) target: {{.OS}}, {{.Arch}} - --help + --help, --version Shows this help listing. --datadir (default: {{.DefaultDataDir}}) @@ -33,6 +33,17 @@ var usageTmpl = `usage: grumble [options] --ini (default: $DATADIR/grumble.ini) Config file path. + --supw [server-id] + Set password for SuperUser account. Optionally takes + the virtual server to modify as the first positional argument. + + --readsupw [server-id] + Like --supw, but reads from stdin instead. + + --disablesu [server-id] + Disables the SuperUser account. Optionally takes + the virtual server to modify as the first positional argument. + --regen-keys Force grumble to regenerate its global RSA keypair (and certificate). @@ -49,13 +60,17 @@ var usageTmpl = `usage: grumble [options] ` type args struct { - ShowHelp bool - DataDir string - LogPath string - ConfigPath string - RegenKeys bool - SQLiteDB string - CleanUp bool + ShowHelp bool + DataDir string + LogPath string + ConfigPath string + SuperUserPW string + ReadPass bool + DisablePass bool + RegenKeys bool + ServerId int64 + SQLiteDB string + CleanUp bool } func defaultDataDir() string { @@ -90,11 +105,17 @@ var Args args func init() { flag.Usage = Usage + flag.BoolVar(&Args.ShowHelp, "version", false, "") flag.BoolVar(&Args.ShowHelp, "help", false, "") + flag.StringVar(&Args.DataDir, "datadir", defaultDataDir(), "") flag.StringVar(&Args.LogPath, "log", "", "") flag.StringVar(&Args.ConfigPath, "ini", "", "") + flag.StringVar(&Args.SuperUserPW, "supw", "", "") + flag.BoolVar(&Args.ReadPass, "readsupw", false, "") + flag.BoolVar(&Args.DisablePass, "disablesu", false, "") + flag.BoolVar(&Args.RegenKeys, "regen-keys", false, "") flag.StringVar(&Args.SQLiteDB, "import-murmurdb", "", "") diff --git a/cmd/grumble/grumble.go b/cmd/grumble/grumble.go index 7ec0f65..fcd5eb2 100644 --- a/cmd/grumble/grumble.go +++ b/cmd/grumble/grumble.go @@ -7,10 +7,12 @@ package main import ( "flag" "fmt" + "io/ioutil" "log" "os" "path/filepath" "regexp" + "strconv" "mumble.info/grumble/pkg/blobstore" "mumble.info/grumble/pkg/logtarget" @@ -29,6 +31,20 @@ func main() { Usage() return } + if Args.ReadPass { + data, err := ioutil.ReadAll(os.Stdin) + if err != nil { + log.Fatalf("Failed to read password from stdin: %v", err) + } + Args.SuperUserPW = string(data) + } + if flag.NArg() > 0 && (Args.SuperUserPW != "" || Args.DisablePass) { + Args.ServerId, err = strconv.ParseInt(flag.Arg(0), 10, 64) + if err != nil { + log.Fatalf("Failed to parse server id %v: %v", flag.Arg(0), err) + return + } + } // Open the data dir to check whether it exists. dataDir, err := os.Open(Args.DataDir) @@ -114,9 +130,7 @@ func main() { // Check whether we should regenerate the default global keypair // and corresponding certificate. - // These are used as the default certificate of all virtual servers - // and the SSH admin console, but can be overridden using the "key" - // and "cert" arguments to Grumble. todo(rubenseyer) implement override by cli + // These are used as the default certificate of all virtual servers. certFn := config.PathValue("CertPath", Args.DataDir) keyFn := config.PathValue("KeyPath", Args.DataDir) shouldRegen := false @@ -232,6 +246,18 @@ func main() { if err != nil { log.Fatalf("Unable to load server: %v", err.Error()) } + + // Check if SuperUser password should be updated. + if Args.ServerId == 0 || Args.ServerId == s.Id { + if Args.DisablePass { + s.cfg.Reset("SuperUserPassword") + log.Printf("Disabled SuperUser for server %v", name) + } else if Args.SuperUserPW != "" { + s.SetSuperUserPassword(Args.SuperUserPW) + log.Printf("Set SuperUser password for server %v", name) + } + } + err = s.FreezeToFile() if err != nil { log.Fatalf("Unable to freeze server to disk: %v", err.Error()) @@ -240,6 +266,14 @@ func main() { } } + // If SuperUser password flags were passed, the servers should not start. + if Args.SuperUserPW != "" || Args.DisablePass { + if len(servers) == 0 { + log.Fatalf("No servers found to set password for") + } + return + } + // If no servers were found, create the default virtual server. if len(servers) == 0 { s, err := NewServer(1, configFile.ServerConfig(1, nil)) diff --git a/cmd/grumble/server.go b/cmd/grumble/server.go index 32cc31c..672ff4f 100644 --- a/cmd/grumble/server.go +++ b/cmd/grumble/server.go @@ -74,8 +74,8 @@ type Server struct { incoming chan *Message voicebroadcast chan *VoiceBroadcast - cfgUpdate chan *KeyValuePair tempRemove chan *Channel + //cfgUpdate chan *KeyValuePair // Signals to the server that a client has been successfully // authenticated.