# 機能設計書 52-ACL管理

## 概要

本ドキュメントは、FreeBSDにおけるファイルシステムのアクセス制御リスト（ACL）管理機能の設計を記述する。getfaclコマンドによるACLの参照と、setfaclコマンドによるACLの設定・変更を提供する。

### 本機能の処理概要

ACL管理機能は、POSIX.1e ACLおよびNFSv4 ACLを用いた、ファイルやディレクトリへのきめ細かなアクセス制御の設定・参照を行う。従来のUNIXパーミッション（owner/group/other）を超えた、ユーザ・グループ単位の詳細なアクセス制御を実現する。

**業務上の目的・背景**：複数のユーザやグループが共有するファイルシステム環境において、従来の3ビットパーミッションモデルでは不十分なアクセス制御が求められる。ACLにより、特定のユーザやグループに対して個別にread/write/execute権限を設定でき、企業環境やマルチテナント環境でのセキュリティポリシーの実現を支援する。

**機能の利用シーン**：共有ディレクトリへの特定ユーザのアクセス許可、プロジェクトチーム単位のファイルアクセス制御、NFSv4環境での継承ACLの設定、セキュリティ監査のためのACL確認など。

**主要な処理内容**：
1. getfaclによるファイル/ディレクトリのACL表示
2. setfaclによるACLエントリの追加・変更・削除
3. POSIX.1e ACL（UFS）とNFSv4 ACL（ZFS）の両方に対応
4. デフォルトACL（ディレクトリの継承ACL）の管理
5. ACLマスクの自動計算
6. 再帰的なACL設定（-Rオプション）
7. NFSv4 ACLの継承フラグ管理

**関連システム・外部連携**：UFS/FFS、ZFSファイルシステムのACLサポート機構、カーネルのsys/acl.h ACL APIとの連携。

**権限による制御**：ファイルの所有者またはroot（スーパーユーザ）のみがACLを変更可能。ACLの参照はファイルへの読み取りアクセス権が必要。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | （CLIツールのため関連画面なし） | - | - |

## 機能種別

CRUD操作（ACLの参照・追加・変更・削除） / セキュリティ管理

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| file | path | Yes | 対象ファイル/ディレクトリパス | 存在するパス |
| -m entries | string | No | マージするACLエントリ | POSIX.1e/NFSv4 ACL形式 |
| -M file | path | No | ACLエントリを含むファイル | ファイルが存在すること |
| -x entries | string | No | 削除するACLエントリ | 有効なACLエントリ形式 |
| -a position entries | string | No | 指定位置にACLエントリを追加 | 有効な位置とACL形式 |
| -b | flag | No | 拡張ACLを削除 | - |
| -k | flag | No | デフォルトACLを削除 | - |
| -d | flag | No | デフォルトACLを操作対象にする | getfaclのみ |
| -R | flag | No | 再帰的に操作 | setfaclのみ |
| -h | flag | No | シンボリックリンク自体を操作 | - |
| -n | flag | No | 数値IDで表示 | getfaclのみ |

### 入力データソース

- コマンドライン引数
- 標準入力（パイプ経由のファイルリスト、-Mオプション用ACLファイル）
- ファイルシステムの既存ACL情報

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ACLテキスト | string | POSIX.1e/NFSv4形式のACL文字列 |
| ファイルオーナー情報 | string | ファイルのowner/group名 |
| エラーメッセージ | string | 操作失敗時のエラー情報 |

### 出力先

- 標準出力（getfaclのACL表示）
- ファイルシステム（setfaclによるACL変更）
- 標準エラー出力（エラーメッセージ）

## 処理フロー

### 処理シーケンス

```
[getfacl]
1. コマンドライン引数解析
   └─ オプション（-d, -h, -n, -q, -s, -v等）の解析
2. 対象ファイルの情報取得
   └─ stat()/lstat()でファイル情報を取得
3. ACLタイプ判定
   └─ pathconf(_PC_ACL_NFS4)でNFSv4 ACL対応を確認
4. ACL取得
   └─ acl_get_file()/acl_get_link_np()でACLを取得
5. ACLテキスト変換・出力
   └─ acl_to_text_np()でテキスト形式に変換し表示

[setfacl]
1. コマンドライン引数解析
   └─ 操作種別（-m, -x, -b, -k, -a）とACLエントリの解析
2. FTSによるファイルツリー走査（-R時）
3. 対象ファイルのACLタイプ判定
4. 既存ACL取得
5. ACL操作実行（マージ/削除/追加/クリア）
6. マスク再計算（need_mask時）
7. ACL設定
   └─ acl_set_file()/acl_set_link_np()でACLを設定
```

### フローチャート

```mermaid
flowchart TD
    A[コマンド開始] --> B{getfacl or setfacl?}
    B -->|getfacl| C[ファイルstat取得]
    C --> D[ACLタイプ判定 NFS4/POSIX]
    D --> E[acl_get_file/acl_get_link_np]
    E --> F{ACL取得成功?}
    F -->|Yes| G[acl_to_text_np で変換]
    F -->|No| H[acl_from_mode_np でフォールバック]
    G --> I[標準出力に表示]
    H --> I
    B -->|setfacl| J[ACLエントリ解析]
    J --> K[FTSでファイル走査]
    K --> L[既存ACL取得]
    L --> M{操作種別}
    M -->|merge| N[merge_acl]
    M -->|remove| O[remove_acl]
    M -->|add| P[add_acl]
    M -->|remove_ext| Q[remove_ext]
    N --> R{マスク再計算?}
    O --> R
    P --> R
    Q --> R
    R -->|Yes| S[マスク計算]
    R -->|No| T[ACL設定]
    S --> T
    T --> U[acl_set_file/acl_set_link_np]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-52-01 | ACLタイプ自動判定 | pathconf(_PC_ACL_NFS4)でNFSv4 ACL対応を判定し、対応する場合はACL_TYPE_NFS4を使用 | ACL操作開始時 |
| BR-52-02 | デフォルトACL制限 | NFSv4 ACLにはデフォルトACLが存在しない | -dオプション使用時にNFSv4 ACLの場合 |
| BR-52-03 | 継承フラグクリア | 再帰モードでファイルにACL設定時、NFSv4の継承フラグを除去 | -R指定かつ通常ファイル |
| BR-52-04 | マスク自動計算 | ACLマージ操作後、-n未指定時にマスクエントリを自動計算 | merge操作後 |
| BR-52-05 | trivial ACLスキップ | -sオプション指定時、trivialなACLは表示しない | getfacl -s使用時 |

### 計算ロジック

ACLマスク計算: マスクエントリは、全てのnamed user/named group/group ownerエントリの権限のORとして算出される。

## データベース操作仕様

### 操作別データベース影響一覧

本機能はデータベースを使用しない。ファイルシステムのACLメタデータを直接操作する。

| 操作 | 対象 | 操作種別 | 概要 |
|-----|------|---------|------|
| ACL参照 | ファイルACL | READ | acl_get_file()による取得 |
| ACL設定 | ファイルACL | WRITE | acl_set_file()による設定 |
| ACL削除 | ファイルACL | DELETE | acl_delete_def_file()による削除 |

### テーブル別操作詳細

該当なし（ファイルシステムメタデータ）。

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 1 | 権限エラー | ファイル所有者でもrootでもない | 適切な権限で実行 |
| 1 | ファイル不存在 | 指定パスが存在しない | パスを確認 |
| 1 | ACL非対応 | ファイルシステムがACLをサポートしない | ACL対応FSにマウント |
| 1 | 不正ACL形式 | ACLエントリの書式が不正 | ACL形式を確認 |
| 1 | NFSv4デフォルトACL | NFSv4 ACLに対するデフォルトACL操作 | -dオプションを除去 |

### リトライ仕様

リトライ処理なし。エラー発生時は警告を出力し、次のファイルの処理を継続する。

## トランザクション仕様

ファイル単位でACL操作が行われる。複数ファイルへの再帰操作中にエラーが発生した場合、既に完了したファイルのACL変更はロールバックされない。

## パフォーマンス要件

特定のパフォーマンス要件なし。ファイルシステムのメタデータ操作であるため、通常は即時完了する。大量ファイルへの再帰操作時はI/Oバウンドとなる。

## セキュリティ考慮事項

- ファイル所有者またはrootのみがACLを変更可能（カーネルレベルで強制）
- ACLはファイルシステムのセキュリティモデルの一部であり、MACフレームワークと共存可能
- NFSv4 ACLは継承フラグにより、新規作成ファイルに自動的にACLを伝播可能

## 備考

- FreeBSDはPOSIX.1e ACL（UFS向け）とNFSv4 ACL（ZFS向け）の2種類をサポート
- getfaclはTrustedBSDプロジェクトで開発された（Robert N M Watson, 1999年）
- setfaclはChris D. Faulhaberにより開発（2001年）

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

ACL操作で使用されるデータ構造を理解する。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | acl.h | `sys/sys/acl.h` | acl_t、acl_entry_t等のACLデータ型定義 |
| 1-2 | setfacl.h | `bin/setfacl/setfacl.h` | setfacl内部で使用する構造体・関数宣言 |

**読解のコツ**: FreeBSDのACL APIはPOSIX.1e標準に準拠しているが、NFSv4 ACL対応のために`_np`サフィックスの非POSIX拡張関数（acl_get_link_np、acl_to_text_np等）が追加されている。

#### Step 2: getfaclのエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | getfacl.c | `bin/getfacl/getfacl.c` | getfaclコマンドの全実装（単一ファイル） |

**主要処理フロー**:
1. **48-57行目**: long_optionsの定義（--default, --numeric, --omit-header, --skip-base）
2. **59-63行目**: usage()関数
3. **66-77行目**: getuname()/getgname() - UID/GIDの名前解決
4. **92-200行目**: print_acl() - ACL取得・表示のコア関数
5. **101-108行目**: stat()/lstat()によるファイル情報取得
6. **110-124行目**: pathconf(_PC_ACL_NFS4)によるACLタイプ判定
7. **126-129行目**: acl_get_file()/acl_get_link_np()によるACL取得
8. **136-158行目**: -sオプション時のtrivial ACLスキップ処理
9. **187行目**: acl_to_text_np()によるテキスト変換
10. **221-287行目**: main()関数 - オプション解析とファイル処理ループ

#### Step 3: setfaclのエントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | setfacl.c | `bin/setfacl/setfacl.c` | setfaclコマンドのメイン処理 |

**主要処理フロー**:
- **43-49行目**: 操作定数定義（OP_MERGE_ACL, OP_REMOVE_DEF等）
- **52-57行目**: sf_entry構造体 - ACL操作のTAILQエントリ
- **60-68行目**: グローバルフラグ（have_mask, n_flag, R_flag等）
- **130-168行目**: clear_inheritance_flags() - 再帰モードでの継承フラグ除去
- **170-340行目**: handle_file() - ファイル単位のACL操作コア処理
- **238-300行目**: 操作種別に応じたACL変更（merge/remove/add/clear）

#### Step 4: ACL操作ユーティリティを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | merge.c | `bin/setfacl/merge.c` | ACLマージ処理 |
| 4-2 | remove.c | `bin/setfacl/remove.c` | ACL削除処理 |
| 4-3 | mask.c | `bin/setfacl/mask.c` | ACLマスク計算処理 |
| 4-4 | util.c | `bin/setfacl/util.c` | ユーティリティ関数 |

### プログラム呼び出し階層図

```
getfacl (bin/getfacl/getfacl.c)
    |
    +-- main()
        +-- print_acl()
        |   +-- stat() / lstat()
        |   +-- pathconf(_PC_ACL_NFS4)
        |   +-- acl_get_file() / acl_get_link_np()
        |   +-- acl_is_trivial_np()
        |   +-- acl_to_text_np()
        |   +-- acl_free()
        +-- print_acl_from_stdin()

setfacl (bin/setfacl/setfacl.c)
    |
    +-- main()
        +-- acl_from_text() [エントリ解析]
        +-- fts_open() / fts_read() [ファイル走査]
        +-- handle_file()
            +-- pathconf(_PC_ACL_NFS4)
            +-- acl_get_file() / acl_get_link_np()
            +-- merge_acl() [merge.c]
            +-- remove_acl() [remove.c]
            +-- add_acl() [merge.c]
            +-- remove_ext() [remove.c]
            +-- clear_inheritance_flags()
            +-- calc_mask() [mask.c]
            +-- acl_set_file() / acl_set_link_np()
```

### データフロー図

```
[入力]                    [処理]                         [出力]

コマンドライン ────▶ getfacl                    ────▶ 標準出力(ACLテキスト)
ファイルパス   ────▶ (getfacl.c)
                     acl_get_file() ◀── カーネルACLサブシステム

コマンドライン ────▶ setfacl                    ────▶ ファイルシステム
ACLエントリ   ────▶ (setfacl.c)                       (ACLメタデータ更新)
ACLファイル(-M)────▶   |
                     acl_set_file() ──▶ カーネルACLサブシステム
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| getfacl.c | `bin/getfacl/getfacl.c` | ソース | getfaclコマンド全実装 |
| setfacl.c | `bin/setfacl/setfacl.c` | ソース | setfaclコマンドメイン処理 |
| setfacl.h | `bin/setfacl/setfacl.h` | ヘッダ | setfacl内部構造体・関数宣言 |
| merge.c | `bin/setfacl/merge.c` | ソース | ACLマージ処理 |
| remove.c | `bin/setfacl/remove.c` | ソース | ACL削除処理 |
| mask.c | `bin/setfacl/mask.c` | ソース | ACLマスク計算 |
| util.c | `bin/setfacl/util.c` | ソース | ユーティリティ関数 |
| file.c | `bin/setfacl/file.c` | ソース | ファイルからのACL読み込み |
| acl.h | `sys/sys/acl.h` | ヘッダ | カーネルACL API定義 |
| getfacl.1 | `bin/getfacl/getfacl.1` | マニュアル | getfaclマニュアルページ |
| setfacl.1 | `bin/setfacl/setfacl.1` | マニュアル | setfaclマニュアルページ |
