aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/app
diff options
context:
space:
mode:
authorOphestra <cat@gensokyo.uk>2025-10-29 03:40:09 +0900
committerOphestra <cat@gensokyo.uk>2025-10-29 03:40:09 +0900
commit274686d10d3386a41f8fb6bc3363269a734afe0e (patch)
tree59ce81d5617cf5e1f67b819dab49b83b71d8ff93 /internal/app
parent65342d588ff061d2130e6379d86a26be90c908ae (diff)
internal/validate: relocate from app
These are free of the dispatcher from internal/app. This change relocates them into their own package. Signed-off-by: Ophestra <cat@gensokyo.uk>
Diffstat (limited to 'internal/app')
-rw-r--r--internal/app/outcome.go2
-rw-r--r--internal/app/path.go15
-rw-r--r--internal/app/path_test.go88
-rw-r--r--internal/app/spaccount.go3
-rw-r--r--internal/app/spcontainer.go3
-rw-r--r--internal/app/sysconf.go8
-rw-r--r--internal/app/sysconf_test.go17
-rw-r--r--internal/app/username.go12
-rw-r--r--internal/app/username_test.go28
9 files changed, 5 insertions, 171 deletions
diff --git a/internal/app/outcome.go b/internal/app/outcome.go
index f462dfd5..237095af 100644
--- a/internal/app/outcome.go
+++ b/internal/app/outcome.go
@@ -43,7 +43,7 @@ type outcomeState struct {
Identity int
// Copied from Identity.
identity *stringPair[int]
- // Returned by [Hsu.MustIDMsg].
+ // Returned by [Hsu.MustID].
UserID int
// Target init namespace uid resolved from UserID and identity.
uid *stringPair[int]
diff --git a/internal/app/path.go b/internal/app/path.go
deleted file mode 100644
index 493dfe39..00000000
--- a/internal/app/path.go
+++ /dev/null
@@ -1,15 +0,0 @@
-package app
-
-import (
- "path/filepath"
- "strings"
-)
-
-func deepContainsH(basepath, targpath string) (bool, error) {
- const upper = ".." + string(filepath.Separator)
-
- rel, err := filepath.Rel(basepath, targpath)
- return err == nil &&
- rel != ".." &&
- !strings.HasPrefix(rel, upper), err
-}
diff --git a/internal/app/path_test.go b/internal/app/path_test.go
deleted file mode 100644
index 1f2d8fa6..00000000
--- a/internal/app/path_test.go
+++ /dev/null
@@ -1,88 +0,0 @@
-package app
-
-import (
- "testing"
-)
-
-func TestDeepContainsH(t *testing.T) {
- t.Parallel()
-
- testCases := []struct {
- name string
- basepath string
- targpath string
- want bool
- wantErr bool
- }{
- {
- name: "empty",
- want: true,
- },
- {
- name: "equal abs",
- basepath: "/run",
- targpath: "/run",
- want: true,
- },
- {
- name: "equal rel",
- basepath: "./run",
- targpath: "run",
- want: true,
- },
- {
- name: "contains abs",
- basepath: "/run",
- targpath: "/run/dbus",
- want: true,
- },
- {
- name: "inverse contains abs",
- basepath: "/run/dbus",
- targpath: "/run",
- want: false,
- },
- {
- name: "contains rel",
- basepath: "../run",
- targpath: "../run/dbus",
- want: true,
- },
- {
- name: "inverse contains rel",
- basepath: "../run/dbus",
- targpath: "../run",
- want: false,
- },
- {
- name: "weird abs",
- basepath: "/run/dbus",
- targpath: "/run/dbus/../current-system",
- want: false,
- },
- {
- name: "weird rel",
- basepath: "../run/dbus",
- targpath: "../run/dbus/../current-system",
- want: false,
- },
-
- {
- name: "invalid mix",
- basepath: "/run",
- targpath: "./run",
- wantErr: true,
- },
- }
-
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- t.Parallel()
- if got, err := deepContainsH(tc.basepath, tc.targpath); (err != nil) != tc.wantErr {
- t.Errorf("deepContainsH() error = %v, wantErr %v", err, tc.wantErr)
- } else if got != tc.want {
- t.Errorf("deepContainsH() = %v, want %v", got, tc.want)
- }
- })
- }
-}
diff --git a/internal/app/spaccount.go b/internal/app/spaccount.go
index 7da54366..c9f08fe9 100644
--- a/internal/app/spaccount.go
+++ b/internal/app/spaccount.go
@@ -6,6 +6,7 @@ import (
"syscall"
"hakurei.app/container/fhs"
+ "hakurei.app/internal/validate"
)
func init() { gob.Register(spAccountOp{}) }
@@ -21,7 +22,7 @@ func (s spAccountOp) toSystem(state *outcomeStateSys) error {
}
// default is applied in toContainer
- if state.Container.Username != "" && !isValidUsername(state.Container.Username) {
+ if state.Container.Username != "" && !validate.IsValidUsername(state.Container.Username) {
return newWithMessage(fmt.Sprintf("invalid user name %q", state.Container.Username))
}
return nil
diff --git a/internal/app/spcontainer.go b/internal/app/spcontainer.go
index 65071f7c..d411cb9f 100644
--- a/internal/app/spcontainer.go
+++ b/internal/app/spcontainer.go
@@ -16,6 +16,7 @@ import (
"hakurei.app/container/fhs"
"hakurei.app/container/seccomp"
"hakurei.app/hst"
+ "hakurei.app/internal/validate"
"hakurei.app/message"
"hakurei.app/system"
"hakurei.app/system/acl"
@@ -243,7 +244,7 @@ func (s *spFilesystemOp) toSystem(state *outcomeStateSys) error {
continue
}
- if ok, err := deepContainsH(p[0], hidePaths[i]); err != nil {
+ if ok, err := validate.DeepContainsH(p[0], hidePaths[i]); err != nil {
return &hst.AppError{Step: "determine path hiding outcome", Err: err}
} else if ok {
hidePathMatch[i] = true
diff --git a/internal/app/sysconf.go b/internal/app/sysconf.go
deleted file mode 100644
index 4c5714a9..00000000
--- a/internal/app/sysconf.go
+++ /dev/null
@@ -1,8 +0,0 @@
-package app
-
-//#include <unistd.h>
-import "C"
-
-const _SC_LOGIN_NAME_MAX = C._SC_LOGIN_NAME_MAX
-
-func sysconf(name C.int) int { return int(C.sysconf(name)) }
diff --git a/internal/app/sysconf_test.go b/internal/app/sysconf_test.go
deleted file mode 100644
index fb0c7f8a..00000000
--- a/internal/app/sysconf_test.go
+++ /dev/null
@@ -1,17 +0,0 @@
-package app
-
-import "testing"
-
-const (
- _POSIX_LOGIN_NAME_MAX = 9
-)
-
-func TestSysconf(t *testing.T) {
- t.Parallel()
-
- t.Run("LOGIN_NAME_MAX", func(t *testing.T) {
- if got := sysconf(_SC_LOGIN_NAME_MAX); got < _POSIX_LOGIN_NAME_MAX {
- t.Errorf("sysconf(_SC_LOGIN_NAME_MAX): %d < _POSIX_LOGIN_NAME_MAX", got)
- }
- })
-}
diff --git a/internal/app/username.go b/internal/app/username.go
deleted file mode 100644
index 566daf5f..00000000
--- a/internal/app/username.go
+++ /dev/null
@@ -1,12 +0,0 @@
-package app
-
-import "regexp"
-
-// nameRegex is the default NAME_REGEX value from adduser.
-var nameRegex = regexp.MustCompilePOSIX(`^[a-zA-Z][a-zA-Z0-9_-]*\$?$`)
-
-// isValidUsername returns whether the argument is a valid username
-func isValidUsername(username string) bool {
- return len(username) < sysconf(_SC_LOGIN_NAME_MAX) &&
- nameRegex.MatchString(username)
-}
diff --git a/internal/app/username_test.go b/internal/app/username_test.go
deleted file mode 100644
index 1b2e0459..00000000
--- a/internal/app/username_test.go
+++ /dev/null
@@ -1,28 +0,0 @@
-package app
-
-import (
- "strings"
- "testing"
-)
-
-func TestIsValidUsername(t *testing.T) {
- t.Parallel()
-
- t.Run("long", func(t *testing.T) {
- if isValidUsername(strings.Repeat("a", sysconf(_SC_LOGIN_NAME_MAX))) {
- t.Errorf("isValidUsername unexpected true")
- }
- })
-
- t.Run("regexp", func(t *testing.T) {
- if isValidUsername("0") {
- t.Errorf("isValidUsername unexpected true")
- }
- })
-
- t.Run("valid", func(t *testing.T) {
- if !isValidUsername("alice") {
- t.Errorf("isValidUsername unexpected false")
- }
- })
-}