blob: 7ab95740882c9afc1c3cdd1a1df1f3140a6a824c [file] [log] [blame]
package impl
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"os"
"os/user"
"strconv"
sflag "veyron.io/veyron/veyron/services/mgmt/suidhelper/impl/flag"
)
type WorkParameters struct {
uid int
gid int
workspace string
logDir string
argv0 string
argv []string
envv []string
dryrun bool
remove bool
}
type ArgsSavedForTest struct {
Uname string
Workpace string
Run string
LogDir string
}
const SavedArgs = "VEYRON_SAVED_ARGS"
var (
flagUsername, flagWorkspace, flagLogDir, flagRun *string
flagMinimumUid *int64
flagRemove *bool
)
func init() {
setupFlags(nil)
}
func setupFlags(fs *flag.FlagSet) {
if fs != nil {
sflag.SetupFlags(fs)
}
flagUsername = sflag.Username
flagWorkspace = sflag.Workspace
flagLogDir = sflag.LogDir
flagRun = sflag.Run
flagMinimumUid = sflag.MinimumUid
flagRemove = sflag.Remove
}
// ParseArguments populates the WorkParameter object from the provided args
// and env strings.
func (wp *WorkParameters) ProcessArguments(fs *flag.FlagSet, env []string) error {
if *flagRemove {
wp.remove = true
wp.argv = fs.Args()
return nil
}
username := *flagUsername
if username == "" {
return fmt.Errorf("--username missing")
}
usr, err := user.Lookup(username)
if err != nil {
return fmt.Errorf("--username %s: unknown user", username)
}
uid, err := strconv.ParseInt(usr.Uid, 0, 32)
if err != nil {
return fmt.Errorf("user.Lookup() returned an invalid uid %v", usr.Uid)
}
gid, err := strconv.ParseInt(usr.Gid, 0, 32)
if err != nil {
return fmt.Errorf("user.Lookup() returned an invalid gid %v", usr.Gid)
}
// Uids less than 501 can be special so we forbid running as them.
if uid < *flagMinimumUid {
return fmt.Errorf("suidhelper does not permit uids less than %d", *flagMinimumUid)
}
// Preserve the arguments for examination by the test harness if executed
// in the course of a test.
if os.Getenv("VEYRON_SUIDHELPER_TEST") != "" {
b := new(bytes.Buffer)
enc := json.NewEncoder(b)
enc.Encode(ArgsSavedForTest{
Uname: *flagUsername,
Workpace: *flagWorkspace,
Run: *flagRun,
LogDir: *flagLogDir,
})
env = append(env, SavedArgs+"="+b.String())
wp.dryrun = true
}
wp.uid = int(uid)
wp.gid = int(gid)
wp.workspace = *flagWorkspace
wp.argv0 = *flagRun
wp.logDir = *flagLogDir
wp.argv = append([]string{wp.argv0}, fs.Args()...)
// TODO(rjkroege): Reduce the environment to the absolute minimum needed.
wp.envv = env
return nil
}