blob: 964f910e4b7464172a11bb7175c42727113075df [file] [log] [blame]
package impl
import (
"bytes"
"encoding/json"
"flag"
"fmt"
"os"
"os/user"
"strconv"
)
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
var flagMinimumUid *int64
func init() {
// Add flags to global set.
setupFlags(flag.CommandLine)
}
func setupFlags(fs *flag.FlagSet) {
flagUsername = fs.String("username", "", "The UNIX user name used for the other functions of this tool.")
flagWorkspace = fs.String("workspace", "", "Path to the application's workspace directory.")
flagStdoutLog = fs.String("stdoutlog", "", "Path to the stdout log file.")
flagStderrLog = fs.String("stderrlog", "", "Path to the stdin log file.")
flagRun = fs.String("run", "", "Path to the application to exec.")
flagMinimumUid = fs.Int64("minuid", uidThreshold, "UIDs cannot be less than this number.")
}
// 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
}