aboutsummaryrefslogtreecommitdiffhomepage
path: root/internal/system/acl
diff options
context:
space:
mode:
Diffstat (limited to 'internal/system/acl')
-rw-r--r--internal/system/acl/acl.go33
-rw-r--r--internal/system/acl/acl_test.go276
-rw-r--r--internal/system/acl/libacl-helper.c90
-rw-r--r--internal/system/acl/libacl-helper.go40
-rw-r--r--internal/system/acl/libacl-helper.h4
-rw-r--r--internal/system/acl/libacl-helper_test.go60
-rw-r--r--internal/system/acl/perms.go18
-rw-r--r--internal/system/acl/perms_test.go30
8 files changed, 0 insertions, 551 deletions
diff --git a/internal/system/acl/acl.go b/internal/system/acl/acl.go
deleted file mode 100644
index 366ad533..00000000
--- a/internal/system/acl/acl.go
+++ /dev/null
@@ -1,33 +0,0 @@
-// Package acl implements simple ACL manipulation via libacl.
-package acl
-
-/*
-#cgo linux pkg-config: --static libacl
-
-#include "libacl-helper.h"
-*/
-import "C"
-
-type Perm C.acl_perm_t
-
-const (
- Read Perm = C.ACL_READ
- Write Perm = C.ACL_WRITE
- Execute Perm = C.ACL_EXECUTE
-)
-
-// Update replaces ACL_USER entry with qualifier uid.
-func Update(name string, uid int, perms ...Perm) error {
- var p *Perm
- if len(perms) > 0 {
- p = &perms[0]
- }
-
- r, err := C.hakurei_acl_update_file_by_uid(
- C.CString(name),
- C.uid_t(uid),
- (*C.acl_perm_t)(p),
- C.size_t(len(perms)),
- )
- return newAclPathError(name, int(r), err)
-}
diff --git a/internal/system/acl/acl_test.go b/internal/system/acl/acl_test.go
deleted file mode 100644
index b0dd58d7..00000000
--- a/internal/system/acl/acl_test.go
+++ /dev/null
@@ -1,276 +0,0 @@
-package acl_test
-
-import (
- "bufio"
- "bytes"
- "errors"
- "fmt"
- "io"
- "os"
- "os/exec"
- "path"
- "reflect"
- "strconv"
- "testing"
-
- "hakurei.app/internal/system/acl"
-)
-
-const testFileName = "acl.test"
-
-var (
- uid = os.Geteuid()
- cred = int32(os.Geteuid())
-)
-
-func TestUpdate(t *testing.T) {
- if os.Getenv("GO_TEST_SKIP_ACL") == "1" {
- t.Log("acl test skipped")
- t.SkipNow()
- }
-
- testFilePath := path.Join(t.TempDir(), testFileName)
-
- if f, err := os.Create(testFilePath); err != nil {
- t.Fatalf("Create: error = %v", err)
- } else {
- if err = f.Close(); err != nil {
- t.Fatalf("Close: error = %v", err)
- }
- }
- defer func() {
- if err := os.Remove(testFilePath); err != nil {
- t.Fatalf("Remove: error = %v", err)
- }
- }()
-
- cur := getfacl(t, testFilePath)
-
- t.Run("default entry count", func(t *testing.T) {
- if len(cur) != 3 {
- t.Fatalf("unexpected test file acl length %d", len(cur))
- }
- })
-
- t.Run("default clear mask", func(t *testing.T) {
- if err := acl.Update(testFilePath, uid); err != nil {
- t.Fatalf("Update: error = %v", err)
- }
- if cur = getfacl(t, testFilePath); len(cur) != 4 {
- t.Fatalf("Update: %v", cur)
- }
- })
-
- t.Run("default clear consistency", func(t *testing.T) {
- if err := acl.Update(testFilePath, uid); err != nil {
- t.Fatalf("Update: error = %v", err)
- }
- if val := getfacl(t, testFilePath); !reflect.DeepEqual(val, cur) {
- t.Fatalf("Update: %v, want %v", val, cur)
- }
- })
-
- testUpdate(t, testFilePath, "r--", cur, fAclPermRead, acl.Read)
- testUpdate(t, testFilePath, "-w-", cur, fAclPermWrite, acl.Write)
- testUpdate(t, testFilePath, "--x", cur, fAclPermExecute, acl.Execute)
- testUpdate(t, testFilePath, "-wx", cur, fAclPermWrite|fAclPermExecute, acl.Write, acl.Execute)
- testUpdate(t, testFilePath, "r-x", cur, fAclPermRead|fAclPermExecute, acl.Read, acl.Execute)
- testUpdate(t, testFilePath, "rw-", cur, fAclPermRead|fAclPermWrite, acl.Read, acl.Write)
- testUpdate(t, testFilePath, "rwx", cur, fAclPermRead|fAclPermWrite|fAclPermExecute, acl.Read, acl.Write, acl.Execute)
-}
-
-func testUpdate(t *testing.T, testFilePath, name string, cur []*getFAclResp, val fAclPerm, perms ...acl.Perm) {
- t.Run(name, func(t *testing.T) {
- t.Cleanup(func() {
- if err := acl.Update(testFilePath, uid); err != nil {
- t.Fatalf("Update: error = %v", err)
- }
- if v := getfacl(t, testFilePath); !reflect.DeepEqual(v, cur) {
- t.Fatalf("Update: %v, want %v", v, cur)
- }
- })
-
- if err := acl.Update(testFilePath, uid, perms...); err != nil {
- t.Fatalf("Update: error = %v", err)
- }
- r := respByCred(getfacl(t, testFilePath), fAclTypeUser, cred)
- if r == nil {
- t.Fatalf("Update did not add an ACL entry")
- }
- if !r.equals(fAclTypeUser, cred, val) {
- t.Fatalf("Update(%s) = %s", name, r)
- }
- })
-}
-
-type (
- getFAclInvocation struct {
- cmd *exec.Cmd
- val []*getFAclResp
- pe []error
- }
-
- getFAclResp struct {
- typ fAclType
- cred int32
- val fAclPerm
-
- raw []byte
- }
-
- fAclPerm uintptr
- fAclType uint8
-)
-
-const fAclBufSize = 16
-
-const (
- fAclPermRead fAclPerm = 1 << iota
- fAclPermWrite
- fAclPermExecute
-)
-
-const (
- fAclTypeUser fAclType = iota
- fAclTypeGroup
- fAclTypeMask
- fAclTypeOther
-)
-
-func (c *getFAclInvocation) run(name string) error {
- if c.cmd != nil {
- panic("attempted to run twice")
- }
-
- c.cmd = exec.Command("getfacl", "--omit-header", "--absolute-names", "--numeric", name)
-
- scanErr := make(chan error, 1)
- if p, err := c.cmd.StdoutPipe(); err != nil {
- return err
- } else {
- go c.parse(p, scanErr)
- }
-
- if err := c.cmd.Start(); err != nil {
- return err
- }
-
- return errors.Join(<-scanErr, c.cmd.Wait())
-}
-
-func (c *getFAclInvocation) parse(pipe io.Reader, scanErr chan error) {
- c.val = make([]*getFAclResp, 0, 4+fAclBufSize)
-
- s := bufio.NewScanner(pipe)
- for s.Scan() {
- fields := bytes.SplitN(s.Bytes(), []byte{':'}, 3)
- if len(fields) != 3 {
- continue
- }
-
- resp := getFAclResp{}
-
- switch string(fields[0]) {
- case "user":
- resp.typ = fAclTypeUser
- case "group":
- resp.typ = fAclTypeGroup
- case "mask":
- resp.typ = fAclTypeMask
- case "other":
- resp.typ = fAclTypeOther
- default:
- c.pe = append(c.pe, fmt.Errorf("unknown type %s", string(fields[0])))
- continue
- }
-
- if len(fields[1]) == 0 {
- resp.cred = -1
- } else {
- if cred, err := strconv.Atoi(string(fields[1])); err != nil {
- c.pe = append(c.pe, err)
- continue
- } else {
- resp.cred = int32(cred)
- if resp.cred < 0 {
- c.pe = append(c.pe, fmt.Errorf("credential %d out of range", resp.cred))
- continue
- }
- }
- }
-
- if len(fields[2]) != 3 {
- c.pe = append(c.pe, fmt.Errorf("invalid perm length %d", len(fields[2])))
- continue
- } else {
- switch fields[2][0] {
- case 'r':
- resp.val |= fAclPermRead
- case '-':
- default:
- c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][0]))
- continue
- }
- switch fields[2][1] {
- case 'w':
- resp.val |= fAclPermWrite
- case '-':
- default:
- c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][1]))
- continue
- }
- switch fields[2][2] {
- case 'x':
- resp.val |= fAclPermExecute
- case '-':
- default:
- c.pe = append(c.pe, fmt.Errorf("invalid perm %v", fields[2][2]))
- continue
- }
- }
-
- resp.raw = make([]byte, len(s.Bytes()))
- copy(resp.raw, s.Bytes())
- c.val = append(c.val, &resp)
- }
- scanErr <- s.Err()
-}
-
-func (r *getFAclResp) String() string {
- if r.raw != nil && len(r.raw) > 0 {
- return string(r.raw)
- }
-
- return "(user-initialised resp value)"
-}
-
-func (r *getFAclResp) equals(typ fAclType, cred int32, val fAclPerm) bool {
- return r.typ == typ && r.cred == cred && r.val == val
-}
-
-func getfacl(t *testing.T, name string) []*getFAclResp {
- c := new(getFAclInvocation)
- if err := c.run(name); err != nil {
- t.Fatalf("getfacl: error = %v", err)
- }
- if len(c.pe) != 0 {
- t.Errorf("errors encountered parsing getfacl output\n%s", errors.Join(c.pe...).Error())
- }
- return c.val
-}
-
-func respByCred(v []*getFAclResp, typ fAclType, cred int32) *getFAclResp {
- j := -1
- for i, r := range v {
- if r.typ == typ && r.cred == cred {
- if j != -1 {
- panic("invalid acl")
- }
- j = i
- }
- }
- if j == -1 {
- return nil
- }
- return v[j]
-}
diff --git a/internal/system/acl/libacl-helper.c b/internal/system/acl/libacl-helper.c
deleted file mode 100644
index d1df8167..00000000
--- a/internal/system/acl/libacl-helper.c
+++ /dev/null
@@ -1,90 +0,0 @@
-#include "libacl-helper.h"
-#include <acl/libacl.h>
-#include <stdbool.h>
-#include <stdlib.h>
-#include <sys/acl.h>
-
-int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
- acl_perm_t *perms, size_t plen) {
- int ret;
- bool v;
- int i;
- acl_t acl;
- acl_entry_t entry;
- acl_tag_t tag_type;
- void *qualifier_p;
- acl_permset_t permset;
-
- ret = -1; /* acl_get_file */
- acl = acl_get_file(path_p, ACL_TYPE_ACCESS);
- if (acl == NULL)
- goto out;
-
- /* prune entries by uid */
- for (i = acl_get_entry(acl, ACL_FIRST_ENTRY, &entry); i == 1;
- i = acl_get_entry(acl, ACL_NEXT_ENTRY, &entry)) {
- ret = -2; /* acl_get_tag_type */
- if (acl_get_tag_type(entry, &tag_type) != 0)
- goto out;
- if (tag_type != ACL_USER)
- continue;
-
- ret = -3; /* acl_get_qualifier */
- qualifier_p = acl_get_qualifier(entry);
- if (qualifier_p == NULL)
- goto out;
- v = *(uid_t *)qualifier_p == uid;
- acl_free(qualifier_p);
-
- if (!v)
- continue;
-
- ret = -4; /* acl_delete_entry */
- if (acl_delete_entry(acl, entry) != 0)
- goto out;
- }
-
- if (plen == 0)
- goto set;
-
- ret = -5; /* acl_create_entry */
- if (acl_create_entry(&acl, &entry) != 0)
- goto out;
-
- ret = -6; /* acl_get_permset */
- if (acl_get_permset(entry, &permset) != 0)
- goto out;
-
- ret = -7; /* acl_add_perm */
- for (i = 0; i < plen; i++) {
- if (acl_add_perm(permset, perms[i]) != 0)
- goto out;
- }
-
- ret = -8; /* acl_set_tag_type */
- if (acl_set_tag_type(entry, ACL_USER) != 0)
- goto out;
-
- ret = -9; /* acl_set_qualifier */
- if (acl_set_qualifier(entry, (void *)&uid) != 0)
- goto out;
-
-set:
- ret = -10; /* acl_calc_mask */
- if (acl_calc_mask(&acl) != 0)
- goto out;
-
- ret = -11; /* acl_valid */
- if (acl_valid(acl) != 0)
- goto out;
-
- ret = -12; /* acl_set_file */
- if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) == 0)
- ret = 0;
-
-out:
- free((void *)path_p);
- if (acl != NULL)
- acl_free((void *)acl);
- return ret;
-}
diff --git a/internal/system/acl/libacl-helper.go b/internal/system/acl/libacl-helper.go
deleted file mode 100644
index 22575296..00000000
--- a/internal/system/acl/libacl-helper.go
+++ /dev/null
@@ -1,40 +0,0 @@
-package acl
-
-import "os"
-
-func newAclPathError(name string, r int, err error) error {
- pathError := &os.PathError{Path: name, Err: err}
- switch r {
- case 0:
- return nil
-
- case -1:
- pathError.Op = "acl_get_file"
- case -2:
- pathError.Op = "acl_get_tag_type"
- case -3:
- pathError.Op = "acl_get_qualifier"
- case -4:
- pathError.Op = "acl_delete_entry"
- case -5:
- pathError.Op = "acl_create_entry"
- case -6:
- pathError.Op = "acl_get_permset"
- case -7:
- pathError.Op = "acl_add_perm"
- case -8:
- pathError.Op = "acl_set_tag_type"
- case -9:
- pathError.Op = "acl_set_qualifier"
- case -10:
- pathError.Op = "acl_calc_mask"
- case -11:
- pathError.Op = "acl_valid"
- case -12:
- pathError.Op = "acl_set_file"
-
- default: // unreachable
- pathError.Op = "setfacl"
- }
- return pathError
-}
diff --git a/internal/system/acl/libacl-helper.h b/internal/system/acl/libacl-helper.h
deleted file mode 100644
index b86eb170..00000000
--- a/internal/system/acl/libacl-helper.h
+++ /dev/null
@@ -1,4 +0,0 @@
-#include <sys/acl.h>
-
-int hakurei_acl_update_file_by_uid(const char *path_p, uid_t uid,
- acl_perm_t *perms, size_t plen);
diff --git a/internal/system/acl/libacl-helper_test.go b/internal/system/acl/libacl-helper_test.go
deleted file mode 100644
index 13d23a3c..00000000
--- a/internal/system/acl/libacl-helper_test.go
+++ /dev/null
@@ -1,60 +0,0 @@
-package acl
-
-import (
- "os"
- "reflect"
- "syscall"
- "testing"
-
- "hakurei.app/container"
-)
-
-func TestNewAclPathError(t *testing.T) {
- testCases := []struct {
- name string
- path string
- r int
- err error
- want error
- }{
- {"nil", container.Nonexistent, 0, syscall.ENOTRECOVERABLE, nil},
-
- {"acl_get_file", container.Nonexistent, -1, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_get_file", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_get_tag_type", container.Nonexistent, -2, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_get_tag_type", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_get_qualifier", container.Nonexistent, -3, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_get_qualifier", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_delete_entry", container.Nonexistent, -4, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_delete_entry", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_create_entry", container.Nonexistent, -5, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_create_entry", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_get_permset", container.Nonexistent, -6, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_get_permset", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_add_perm", container.Nonexistent, -7, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_add_perm", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_set_tag_type", container.Nonexistent, -8, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_set_tag_type", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_set_qualifier", container.Nonexistent, -9, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_set_qualifier", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_calc_mask", container.Nonexistent, -10, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_calc_mask", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_valid", container.Nonexistent, -11, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_valid", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"acl_set_file", container.Nonexistent, -12, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "acl_set_file", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
-
- {"acl", container.Nonexistent, -13, syscall.ENOTRECOVERABLE,
- &os.PathError{Op: "setfacl", Path: container.Nonexistent, Err: syscall.ENOTRECOVERABLE}},
- {"invalid", container.Nonexistent, -0xdead, nil,
- &os.PathError{Op: "setfacl", Path: container.Nonexistent}},
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- err := newAclPathError(tc.path, tc.r, tc.err)
- if !reflect.DeepEqual(err, tc.want) {
- t.Errorf("newAclPathError: %v, want %v", err, tc.want)
- }
- })
- }
-}
diff --git a/internal/system/acl/perms.go b/internal/system/acl/perms.go
deleted file mode 100644
index fbc99e82..00000000
--- a/internal/system/acl/perms.go
+++ /dev/null
@@ -1,18 +0,0 @@
-package acl
-
-type Perms []Perm
-
-func (ps Perms) String() string {
- var s = []byte("---")
- for _, p := range ps {
- switch p {
- case Read:
- s[0] = 'r'
- case Write:
- s[1] = 'w'
- case Execute:
- s[2] = 'x'
- }
- }
- return string(s)
-}
diff --git a/internal/system/acl/perms_test.go b/internal/system/acl/perms_test.go
deleted file mode 100644
index 3d5e3df5..00000000
--- a/internal/system/acl/perms_test.go
+++ /dev/null
@@ -1,30 +0,0 @@
-package acl_test
-
-import (
- "testing"
-
- "hakurei.app/internal/system/acl"
-)
-
-func TestPerms(t *testing.T) {
- testCases := []struct {
- name string
- perms acl.Perms
- }{
- {"---", acl.Perms{}},
- {"r--", acl.Perms{acl.Read}},
- {"-w-", acl.Perms{acl.Write}},
- {"--x", acl.Perms{acl.Execute}},
- {"rw-", acl.Perms{acl.Read, acl.Read, acl.Write}},
- {"r-x", acl.Perms{acl.Read, acl.Execute, acl.Execute}},
- {"-wx", acl.Perms{acl.Write, acl.Write, acl.Execute, acl.Execute}},
- {"rwx", acl.Perms{acl.Read, acl.Write, acl.Execute}},
- }
- for _, tc := range testCases {
- t.Run(tc.name, func(t *testing.T) {
- if got := tc.perms.String(); got != tc.name {
- t.Errorf("String: %q, want %q", got, tc.name)
- }
- })
- }
-}