| 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 uint32 |
| gid uint32 |
| workspace string |
| stderrLog string |
| stdoutLog string |
| argv0 string |
| argv []string |
| envv []string |
| } |
| |
| type ArgsSavedForTest struct { |
| Uname string |
| Workpace string |
| Run string |
| StdoutLog string |
| StderrLog string |
| } |
| |
| const SavedArgs = "VEYRON_SAVED_ARGS" |
| |
| var ( |
| flagUsername, flagWorkspace, flagStdoutLog, flagStderrLog, flagRun *string |
| flagMinimumUid *int64 |
| ) |
| |
| func init() { |
| setupFlags(nil) |
| } |
| |
| func setupFlags(fs *flag.FlagSet) { |
| if fs != nil { |
| sflag.SetupFlags(fs) |
| } |
| flagUsername = sflag.Username |
| flagWorkspace = sflag.Workspace |
| flagStdoutLog = sflag.StdoutLog |
| flagStderrLog = sflag.StderrLog |
| flagRun = sflag.Run |
| flagMinimumUid = sflag.MinimumUid |
| } |
| |
| // ParseArguments populates the WorkParameter object from the provided args |
| // and env strings. |
| func (wp *WorkParameters) ProcessArguments(fs *flag.FlagSet, env []string) error { |
| 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.ParseUint(usr.Uid, 0, 32) |
| if err != nil { |
| return fmt.Errorf("user.Lookup() returned an invalid uid %v", usr.Uid) |
| } |
| gid, err := strconv.ParseUint(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 uint32(uid) < uint32(*flagMinimumUid) { |
| return fmt.Errorf("suidhelper does not permit uids less than %d", uint32(*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, |
| StdoutLog: *flagStdoutLog, |
| StderrLog: *flagStderrLog, |
| }) |
| env = append(env, SavedArgs+"="+b.String()) |
| } |
| |
| wp.uid = uint32(uid) |
| wp.gid = uint32(gid) |
| wp.workspace = *flagWorkspace |
| wp.argv0 = *flagRun |
| wp.stdoutLog = *flagStdoutLog |
| wp.stderrLog = *flagStderrLog |
| wp.argv = fs.Args() |
| // TODO(rjkroege): Reduce the environment to the absolute minimum needed. |
| wp.envv = env |
| |
| return nil |
| } |