blob: 9e935d206a6edc56ab5a57ef9cd242c437f15d91 [file] [log] [blame]
package impl
import (
"os"
"os/user"
"v.io/core/veyron2/ipc"
"v.io/core/veyron2/verror2"
"v.io/core/veyron2/vlog"
)
type suidHelperState string
var suidHelper suidHelperState
func init() {
u, err := user.Current()
if err != nil {
vlog.Panicf("devicemanager has no current user: %v", err)
}
suidHelper = suidHelperState(u.Username)
}
// isSetuid is defined like this so we can override its
// implementation for tests.
var isSetuid = func(fileStat os.FileInfo) bool {
vlog.VI(2).Infof("running the original isSetuid")
return fileStat.Mode()&os.ModeSetuid == os.ModeSetuid
}
// unameRequiresSuidhelper determines if the the suidhelper must exist
// and be setuid to run an application as system user un. If false, the
// setuidhelper must be invoked with the --dryrun flag to skip making
// system calls that will fail or provide apps with a trivial
// priviledge escalation.
func (dn suidHelperState) suidhelperEnabled(un, helperPath string) (bool, error) {
helperStat, err := os.Stat(helperPath)
if err != nil {
vlog.Errorf("Stat(%v) failed: %v. helper is required.", helperPath, err)
return false, verror2.Make(ErrOperationFailed, nil)
}
haveHelper := isSetuid(helperStat)
switch {
case haveHelper && string(dn) != un:
return true, nil
case haveHelper && string(dn) == un:
return false, verror2.Make(verror2.NoAccess, nil)
default:
return false, nil
}
// Keep the compiler happy.
return false, nil
}
// usernameForVanadiumPrincipal returns the system name that the
// devicemanager will use to invoke apps.
// TODO(rjkroege): This code assumes a desktop target and will need
// to be reconsidered for embedded contexts.
func (i suidHelperState) usernameForPrincipal(ctx ipc.ServerContext, uat BlessingSystemAssociationStore) string {
identityNames := ctx.RemoteBlessings().ForContext(ctx)
systemName, present := uat.SystemAccountForBlessings(identityNames)
if present {
return systemName
} else {
return string(i)
}
}