5.4. 處理 ACL

表格 5.1, "ACL 項目類型" 摘錄 6 種可能的 ACL 項目類型,每個類型定義一個使用者或一群組使用者的許可權。擁有者項目定義使用者所屬檔案或目錄的許可權。所屬群組項目定義檔案的所屬群組許可權。超級使用者可以使用 chownchgrp 變更擁有者或所屬群組,在這樣情況下,擁有群組項目會參照新擁有者和所屬群組。每個命名的使用者項目會定義使用者許可權,而該許可權指定於項目的辨識符號欄位。每個命名的群組項目會定義群組許可權,而該許可權指定於項目的辨識符號欄位。只有命名的使用者和命名的群組擁有的辨識符號欄位不是空的。其他項目定義所有其他使用者許可權。

透過定義那些有效項目的許可項目以及遮罩的項目,遮罩項目會進一步限制由「命名的使用者」、「命名的群組」以及「所屬群組」項目授與的許可權。如果許可權存在於之前提及的任一項目和遮罩中,它們都是有效的。只有包含於遮罩或實際項目的許可權是無效的 -- 表示未授與此許可權。定義在使用者和所屬群組項目的所有許可權永遠有效。表格 5.2, "遮罩存取許可權" 中的範例會示範此機制。

有兩種基本類型的 ACL:最小值 ACL 只包含擁有者、所屬群組和其他類型的項目,對應檔案和目錄的傳統許可權位元。延伸 ACL 則不僅如此。它必須包含遮罩項目而且可以包含命名使用者和命名群組類型的多個項目。

表格 5.1. ACL 項目類型

類型

文字形式

擁有者

user::rwx

命名使用者

user:name:rwx

所屬群組

group::rwx

命名群組

group:name:rwx

遮罩

mask::rwx

其他

other::rwx

表格 5.2. 遮罩存取許可權

項目類型

文字形式

許可權

命名使用者

user:geeko:r-x

r-x

遮罩

mask::rw-

rw-

有效許可權:

r--

5.4.1. ACL 項目和檔案模式許可權位元

圖形 5.1, "最小 ACL:ACL 項目比較許可權位元"圖形 5.2, "延伸 ACL:ACL 項目比較許可權位元" 會列舉最小值 ACL 和延伸 ACL 的兩個案例。圖的結構分成三個區塊 — 左方區塊顯示 ACL 項目的類型格式,中間區塊顯示範例 ACL,而右方區塊則顯示傳統許可權概念的許可權位元,例如,以 ls -l 顯示。在二者案例中,擁有者類別許可權會對應至 ACL 項目擁有者。其他類別許可權會對應個別 ACL 項目。不過,群組類別許可權的對應與這兩個案例不同。

圖形 5.1. 最小 ACL:ACL 項目比較許可權位元

最小 ACL:ACL 項目比較許可權位元

在最小 ACL 案例中 (不含遮罩),群組類別許可權會對應至 ACL 項目所屬群組。這會顯示於 圖形 5.1, "最小 ACL:ACL 項目比較許可權位元"。在延伸 ACL 案例中 (含遮罩),群組類別許可權是對應至遮罩項目。這會顯示於 圖形 5.2, "延伸 ACL:ACL 項目比較許可權位元"

圖形 5.2. 延伸 ACL:ACL 項目比較許可權位元

延伸 ACL:ACL 項目比較許可權位元

此對應方法可以確定應用程式互動順暢,無論它們是否擁有 ACL 支援。透過許可權位元方法所指定的存取許可權,代表藉由 ACL 所做的所有其他「微調」上限。對許可權位元所做的變更會由 ACL 反映,反之亦然。

5.4.2. 含存取 ACL 的目錄

在指令行上使用 getfaclsetfacl 這兩個指令,您就可以存取 ACL。使用這兩個指令的方式如以下範例所示範。

建立目錄之前,使用 umask 指令來定義每次建立檔案物件時,要遮罩的存取許可權。指令 umask 027 會指定完整範圍的許可權 (0) 給擁有者,拒絕群組寫入存取 (2) 以及不提供其他使用者任何許可權 (7),以設定預設許可權。umask 實際上會遮罩相應的許可權位元或關閉它們。如需詳細資訊,請參閱 umask 線上文件。

mkdir mydir 會以 umask 設定的預設許可權建立 mydir 目錄。使用 ls -dl mydir 檢查所有許可權是否指定正確。範例的輸出如下:

drwxr-x--- ... tux project3 ... mydir

使用 getfacl mydir 檢查 ACL 的啟始狀態。會提供類似以下的資訊:

# file: mydir 
# owner: tux 
# group: project3 
user::rwx 
group::r-x 
other::---
     

前三個輸出行顯示目錄的名稱、擁有者和所屬群組。接下來三行包含三個 ACL 項目擁有者、所屬群組和其他。實際上,在此最小 ACL 案例中,getfacl 指令不會產生任何您以 ls 指令無法取得的資訊。

以下列指令修改 ACL 以指定讀取、寫入和執行許可權給另一個使用者 geeko 以及另一個群組 mascots

setfacl -m user:geeko:rwx,group:mascots:rwx mydir

選項 -m 提示 setfacl 修改現有的 ACL。以下引數指示要修改的 ACL 項目 (多個項目由逗點分開)。最後部份指定這些修改要套用至什麼目錄名稱。使用 getfacl 指令,查看產生的 ACL。

# file: mydir 
# owner: tux 
# group: project3 
user::rwx 
user:geeko:rwx 
group::r-x
group:mascots:rwx 
mask::rwx 
other::--- 

除了為使用者 geeko 和群組 mascots 實施的項目之外,已經產生一個遮罩項目。會自動設定遮罩項目讓所有的許可權生效。除非使用 -n 停用此功能,setfacl 會將現有遮罩項目調整為修改過的設定值。遮罩會定義群組類別中所有項目的最大有效存取許可權。此包括命名使用者、命名群組以及所屬群組。ls -dl mydir 顯示的類別群組許可權位元,對應至遮罩項目。

drwxrwx---+ ... tux project3 ... mydir
   

輸出的第一欄包含額外的 +,指示此項目有一個延伸 ACL。

根據 ls 指令的輸出,遮罩項目的許可權包括寫入存取。傳統上,此類的許可權位元表示所屬群組 (在此為 project3) 也擁有目錄 mydir 的寫入存取。然而,所屬群組的有效存取許可權會對應至許可權的重疊部分,該重疊部分定義在所屬群組和遮罩在本範例中是 r-x (請參閱 表格 5.2, "遮罩存取許可權")。就範例中所屬群組的有效許可權而言,即使新增 ACL 項目之後也不會變更有效所有權。

使用 setfaclchmod,編輯遮罩項目。例如,使用 chmod g-w mydir。接著 ls -dl mydir 顯示如下:

drwxr-x---+ ... tux project3 ... mydir

getfacl mydir 提供下列輸出:

# file: mydir 
# owner: tux 
# group: project3 
user::rwx 
user:geeko:rwx          # effective: r-x
group::r-x 
group:mascots:rwx       # effective: r-x 
mask::r-x 
other::---

執行 chmod 指令,從群組類別位元移除寫入許可權之後,ls 指令的輸出就可以知道遮罩位元必須同時變更:寫入許可權再次限制為 mydir 的擁有者。getfacl 的輸出可確認此項結果。此輸出針對有效許可權未對應至原始許可權的所有項目包含一個註解,因為它們是根據遮罩項目過濾的。可以隨時使用 chmod g+w mydir 復原原始許可權。

5.4.3. 含預設 ACL 的目錄

目錄可以有一個預設的 ACL,它是特別的 ACL。建立物件時,它定義目錄中物件繼承的存取許可權。預設 ACL 會影響子目錄和檔案。

5.4.3.1. 預設 ACL 的作用

子目錄的預設 ACL,其許可權傳送至檔案以及子目錄的方法有兩種:

  • 子目錄繼承上層目錄的預設 ACL,當成預設 ACL,也當成存取 ACL。

  • 檔案會將預設 ACL 繼承為存取 ACL。

建立檔案系統的所有系統呼叫,會使用 mode 參數,它會為新建立的檔案系統物件,定義存取許可權。如果上層目錄沒有預設 ACL,umask 定義的許可權位元會從 mode 參數傳送的許可權中去除,將結果指定給新物件。如果上層目錄的預設 ACL 存在,指定給新物件的許可權位元會對應至 mode 參數的許可權重疊部份,以及定義在預設 ACL 的許可權。umask 在此案例中不予處理。

5.4.3.2. 預設 ACL 的應用

以下三個範例顯示目錄和預設 ACL 的主要作業:

  1. 新增預設 ACL 至現有的目錄 mydir,透過:

    setfacl -d -m group:mascots:r-x mydir
    

    setfacl 指令的 -d 選項,提示 setfacl 在預設 ACL 執行以下修改 (-m 選項)。

    仔細查看指令的結果:

    getfacl mydir
    
    # file: mydir 
    # owner: tux 
    # group: project3 
    user::rwx 
    user:geeko:rwx 
    group::r-x
    group:mascots:rwx 
    mask::rwx 
    other::--- 
    default:user::rwx
    default:group::r-x 
    default:group:mascots:r-x 
    default:mask::r-x
    default:other::---
    

    getfacl 傳回存取 ACL 和預設 ACL 二者。預設 ACL 是由開頭為 default 的所有行形成的。雖然您只是在預設 ACL 的 mascots 群組的一個項目執行 setfacl 指令,不過 setfacl 會自動從存取 ACL 複製所有其他項目來建立有效的預設 ACL。預設 ACL 對於存取許可權沒有立即的作用。它們只會在建立檔案系統物件時才有作用。這些新物件只會從其上層目錄的預設 ACL 繼承許可權。

  2. 在下一個範例中,使用 mkdir,在 mydir 目錄中建立子目錄,它會繼承預設 ACL。

    mkdir mydir/mysubdir
    
    getfacl mydir/mysubdir 
    
    # file: mydir/mysubdir 
    # owner: tux 
    # group: project3 
    user::rwx 
    group::r-x 
    group:mascots:r-x 
    mask::r-x
    other::--- 
    default:user::rwx 
    default:group::r-x
    default:group:mascots:r-x 
    default:mask::r-x 
    default:other::---
    

    如預期般,新建立的子目錄 mysubdir 擁有上層目錄預設 ACL 的許可權。mysubdir 的存取 ACL 與 mydir 的預設 ACL 完全相同。目錄傳給其從屬物件的預設 ACL,也是如此。

  3. 使用 touchmydir 目錄建立檔案,例如, touch mydir/myfile。接著 ls -l mydir/myfile 會顯示如下:

    -rw-r-----+ ... tux project3 ... mydir/myfile 
    

    getfacl mydir/myfile 輸出,如下:

    # file: mydir/myfile 
    # owner: tux 
    # group: project3
    user::rw- 
    group::r-x          # effective:r-- 
    group:mascots:r-x   # effective:r-- 
    mask::r-- 
    other::--- 
    

    建立新檔案時,touch 會使用值為 0666模式。這表示檔案建立後,所有使用者類別都有讀取和寫入的許可權,而且在 umask 或預設 ACL 中沒有其它限制 (請參閱 節 5.4.3.1, "預設 ACL 的作用")。實際上,這表示所有未包含在 mode 值中的存取許可權,會從各自的 ACL 項目移除。雖然未從群組類別的 ACL 項目移除許可權,將遮罩項目修改為遮罩許可權,不在此模式中設定。

    此方法可以確定應用程式 (例如編譯器) 與 ACL 的互動平順。您可以建立存取許可權受限的檔案,然後標示成可執行。mask 機制可以保證正確的使用者和群組可以執行它們。

5.4.4. ACL 檢查演算法

任何程序或應用程式授與存取 ACL 保護的檔案系統物件前,會先套用檢查演算法。有個基本規則是,ACL 項目會按照以下順序檢查:擁有者、命名使用者、所屬群組或命名群組以及其他。處理的存取合乎最符合程序的項目。許可權不會累積。

如果程序屬於一個以上的群組而且可能符合多個群組項目,就會變得更複雜。項目是從符合必要許可權的合適項目中隨機選取的。它與觸發最後的結果 "access granted" 的項目無關。同樣地,如果適合的群組項目不包含需要的許可權,隨機選取的項目會觸發最後的結果「拒絕存取」。