Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

issue 2117: disallow admin username #2378

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions cmd/limactl/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ func copyAction(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
u, err := osutil.LimaUser(false)
if err != nil {
return err
}

instDirs := make(map[string]string)
scpFlags := []string{}
scpArgs := []string{}
Expand Down Expand Up @@ -86,6 +83,10 @@ func copyAction(cmd *cobra.Command, args []string) error {
if inst.Status == store.StatusStopped {
return fmt.Errorf("instance %q is stopped, run `limactl start %s` to start the instance", instName, instName)
}
u, err := osutil.LimaUser(false, inst.LimaVersion)
if err != nil {
return err
}
if legacySSH {
scpFlags = append(scpFlags, "-P", fmt.Sprintf("%d", inst.SSHLocalPort))
scpArgs = append(scpArgs, fmt.Sprintf("%[email protected]:%s", u.Username, path[1]))
Expand Down
3 changes: 2 additions & 1 deletion pkg/cidata/cidata.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
"github.com/lima-vm/lima/pkg/sshutil"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/lima-vm/lima/pkg/usrlocalsharelima"
"github.com/lima-vm/lima/pkg/version"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -115,7 +116,7 @@ func GenerateISO9660(instDir, name string, y *limayaml.LimaYAML, udpDNSLocalPort
if err := limayaml.Validate(y, false); err != nil {
return err
}
u, err := osutil.LimaUser(true)
u, err := osutil.LimaUser(true, version.Version)
if err != nil {
return err
}
Expand Down
21 changes: 19 additions & 2 deletions pkg/limayaml/defaults.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/lima-vm/lima/pkg/ptr"
"github.com/lima-vm/lima/pkg/store/dirnames"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/lima-vm/lima/pkg/version/versionutil"
)

const (
Expand Down Expand Up @@ -753,8 +754,10 @@ func fixUpForPlainMode(y *LimaYAML) {

func executeGuestTemplate(format, instDir string, param map[string]string) (bytes.Buffer, error) {
tmpl, err := template.New("").Parse(format)
limaVersion := ReadInstLimaVersion(instDir)

if err == nil {
user, _ := osutil.LimaUser(false)
user, _ := osutil.LimaUser(false, limaVersion)
data := map[string]interface{}{
"Home": fmt.Sprintf("/home/%s.linux", user.Username),
"Name": filepath.Base(instDir),
Expand All @@ -771,9 +774,11 @@ func executeGuestTemplate(format, instDir string, param map[string]string) (byte
}

func executeHostTemplate(format, instDir string, param map[string]string) (bytes.Buffer, error) {
limaVersion := ReadInstLimaVersion(instDir)

tmpl, err := template.New("").Parse(format)
if err == nil {
user, _ := osutil.LimaUser(false)
user, _ := osutil.LimaUser(false, limaVersion)
home, _ := os.UserHomeDir()
limaHome, _ := dirnames.LimaDir()
data := map[string]interface{}{
Expand Down Expand Up @@ -1074,3 +1079,15 @@ func unique(s []string) []string {
}
return list
}

func ReadInstLimaVersion(instDir string) string {
limaVersionFile := filepath.Join(instDir, filenames.LimaVersion)
limaVersion := ""
if version, err := os.ReadFile(limaVersionFile); err == nil {
limaVersion = strings.TrimSpace(string(version))
if _, err = versionutil.Parse(limaVersion); err != nil {
logrus.Warnf("treating lima version %q from %q as very latest release", limaVersion, limaVersionFile)
}
}
return limaVersion
}
3 changes: 2 additions & 1 deletion pkg/limayaml/defaults_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/lima-vm/lima/pkg/ptr"
"github.com/lima-vm/lima/pkg/store/dirnames"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/lima-vm/lima/pkg/version"
"github.com/sirupsen/logrus"
"gotest.tools/v3/assert"
)
Expand Down Expand Up @@ -53,7 +54,7 @@ func TestFillDefault(t *testing.T) {
assert.NilError(t, err)
limaHome, err := dirnames.LimaDir()
assert.NilError(t, err)
user, err := osutil.LimaUser(false)
user, err := osutil.LimaUser(false, version.Version)
assert.NilError(t, err)

guestHome := fmt.Sprintf("/home/%s.linux", user.Username)
Expand Down
3 changes: 2 additions & 1 deletion pkg/limayaml/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/lima-vm/lima/pkg/localpathutil"
"github.com/lima-vm/lima/pkg/networks"
"github.com/lima-vm/lima/pkg/osutil"
"github.com/lima-vm/lima/pkg/version"
"github.com/sirupsen/logrus"
)

Expand Down Expand Up @@ -117,7 +118,7 @@ func Validate(y *LimaYAML, warn bool) error {
return fmt.Errorf("field `memory` has an invalid value: %w", err)
}

u, err := osutil.LimaUser(false)
u, err := osutil.LimaUser(false, version.Version)
if err != nil {
return fmt.Errorf("internal error (not an error of YAML): %w", err)
}
Expand Down
23 changes: 21 additions & 2 deletions pkg/osutil/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"strings"
"sync"

"github.com/lima-vm/lima/pkg/version/versionutil"
"github.com/sirupsen/logrus"
)

Expand All @@ -35,7 +36,10 @@ var (
// regexUsername matches user and group names to be valid for `useradd`.
// `useradd` allows names with a trailing '$', but it feels prudent to map those
// names to the fallback user as well, so the regex does not allow them.
var regexUsername = regexp.MustCompile("^[a-z_][a-z0-9_-]*$")
var (
regexUsername = regexp.MustCompile("^[a-z_][a-z0-9_-]*$")
notAllowedUsernameRegex = regexp.MustCompile(`^admin$`)
)

// regexPath detects valid Linux path.
var regexPath = regexp.MustCompile("^[/a-zA-Z0-9_-]+$")
Expand Down Expand Up @@ -106,11 +110,26 @@ func call(args []string) (string, error) {
return strings.TrimSpace(string(out)), nil
}

func LimaUser(warn bool) (*user.User, error) {
func IsBlockedUsername(username, limaVersion string) bool {
if versionutil.GreaterThan(limaVersion, "0.23.2") {
return notAllowedUsernameRegex.MatchString(username)
}
return false
}

func LimaUser(warn bool, limaVersion string) (*user.User, error) {
cache.warnings = []string{}
cache.Do(func() {
cache.u, cache.err = user.Current()
if cache.err == nil {
// check if the username is blocked
if IsBlockedUsername(cache.u.Username, limaVersion) {
warning := fmt.Sprintf("local user %q is not a allowed (must not match %q); using %q username instead",
cache.u.Username, notAllowedUsernameRegex.String(), fallbackUser)
cache.warnings = append(cache.warnings, warning)
cache.u.Username = fallbackUser
}

if !regexUsername.MatchString(cache.u.Username) {
warning := fmt.Sprintf("local user %q is not a valid Linux username (must match %q); using %q username instead",
cache.u.Username, regexUsername.String(), fallbackUser)
Expand Down
18 changes: 13 additions & 5 deletions pkg/osutil/user_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
)

func TestLimaUserWarn(t *testing.T) {
_, err := LimaUser(true)
_, err := LimaUser(true, "")
assert.NilError(t, err)
}

Expand All @@ -18,29 +18,37 @@ func validUsername(username string) bool {
}

func TestLimaUsername(t *testing.T) {
user, err := LimaUser(false)
user, err := LimaUser(false, "")
assert.NilError(t, err)
// check for reasonable unix user name
assert.Assert(t, validUsername(user.Username), user.Username)
}

func TestLimaUserUid(t *testing.T) {
user, err := LimaUser(false)
user, err := LimaUser(false, "")
assert.NilError(t, err)
_, err = strconv.Atoi(user.Uid)
assert.NilError(t, err)
}

func TestLimaUserGid(t *testing.T) {
user, err := LimaUser(false)
user, err := LimaUser(false, "")
assert.NilError(t, err)
_, err = strconv.Atoi(user.Gid)
assert.NilError(t, err)
}

func TestLimaHomeDir(t *testing.T) {
user, err := LimaUser(false)
user, err := LimaUser(false, "")
assert.NilError(t, err)
// check for absolute unix path (/home)
assert.Assert(t, path.IsAbs(user.HomeDir), user.HomeDir)
}

func TestBlockedUsers(t *testing.T) {
// admin is a blocked username
assert.Assert(t, IsBlockedUsername("admin", "0.23.1") == false, "testing on low version of lima")
assert.Assert(t, IsBlockedUsername("admin", "0.23.3") == true, "testing on high version of lima")
assert.Assert(t, IsBlockedUsername("randomuser", "0.23.1") == false, "testing on low version of lima")
assert.Assert(t, IsBlockedUsername("randomuser", "0.23.3") == false, "testing on low version of lima")
}
10 changes: 9 additions & 1 deletion pkg/sshutil/sshutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ import (
"github.com/lima-vm/lima/pkg/ioutilx"
"github.com/lima-vm/lima/pkg/lockutil"
"github.com/lima-vm/lima/pkg/osutil"
"github.com/lima-vm/lima/pkg/store"
"github.com/lima-vm/lima/pkg/store/dirnames"
"github.com/lima-vm/lima/pkg/store/filenames"
"github.com/lima-vm/lima/pkg/version"
"github.com/sirupsen/logrus"
"golang.org/x/sys/cpu"
)
Expand Down Expand Up @@ -228,7 +230,13 @@ func SSHOpts(instDir string, useDotSSH, forwardAgent, forwardX11, forwardX11Trus
if len(controlSock) >= osutil.UnixPathMax {
return nil, fmt.Errorf("socket path %q is too long: >= UNIX_PATH_MAX=%d", controlSock, osutil.UnixPathMax)
}
u, err := osutil.LimaUser(false)
instName := filepath.Base(instDir)
inst, err := store.Inspect(instName)
limaVersion := version.Version
if err == nil {
limaVersion = inst.LimaVersion
}
u, err := osutil.LimaUser(false, limaVersion)
if err != nil {
return nil, err
}
Expand Down
Loading