摘要

  • IMAP 邮箱 ACL 由“访问标识符—权限”条目组成;同一用户可以同时匹配个人、群组和 anyone,所以一行记录只是授权计算的输入。
  • GETACL 查看规则,LISTRIGHTS 查看服务器能给某个标识符什么权利,MYRIGHTS 才返回当前登录用户的有效结果;三者回答的是不同问题。
  • DELETEACL 删除条目,negative right 则在计算中扣除权利。RFC 4314 澄清了这条边界,同时把身份合并方式和 negative right 支持保留为本地选择。

一次成功保存,并没有回答撤权问题

权限管理界面喜欢把控制呈现成一张表。找到用户名,删除一行,点击保存,系统便宣布这个人已经失去访问权。只有在那一行是唯一授权路径、执行服务器已经重新计算、旧会话也不再沿用缓存时,这个故事才成立。

共享邮箱很早就暴露了它的脆弱。值班队列可以属于一个团队;某人既有直接权限,也属于一个工作组,还可能落入全体用户规则。表里的每一行只是“为什么可以”的一个来源,而不是最后的“到底可以什么”。

RFC 1730 把远端邮箱定义成可由客户端操作的网络对象。用户可以选择文件夹、读取邮件、改变标记和操作服务器上的邮箱状态。多人共享同一对象后,访问控制也必须穿过协议边界;只存在于服务器本地文件系统里的权限,无法让远端客户端理解自己能做什么。

1997 年 1 月发布的 Standards Track RFC 2086 增加了这个表面。服务器在能力列表里宣布 ACL,客户端随后可以读取或修改邮箱上的“标识符—权限”组合,而不需要取得整套本地账号数据库。

一个会话可以带着多个名字到达

一对字段看似简单,真正的难点却藏在“标识符”里。RFC 2086 把 anyone 留给通用身份,连匿名连接也包括在内;服务器接受的登录名对应具体用户;其他字符串可以表示群组,也可以由实现赋予别的本地含义。

同一个会话可以同时符合多项。Fred 既匹配 fred,也匹配 support-team,还匹配 anyone。标准没有强迫所有服务器采用同一种合并算法:实现可以把所有命中的授予取并集,也可以只采用最具体的条目。

这不是客户端可以自行补齐的空白。图形界面看得到行,却看不到服务器实际采用的群组成员关系、强制所有者权限和优先级。同一张可见清单,在两个合规服务器上可能产生不同结果。

协议没有因此集中身份权力,而是让执行者回答最终问题。MYRIGHTS mailbox 由真正要执行下一条命令的服务器计算,返回当前登录用户对这个邮箱的有效权限。它是运行状态的证据,而不是客户端对规则表的猜测。

三个查询对应三层现实

GETACL 返回邮箱保存的标识符与权限条目。它回答“这里声明了哪些规则”,却不说明哪些条目会命中当前用户,也不说明服务器怎样合并它们。

LISTRIGHTS 给定邮箱和标识符,列出可以授予的权利。底层系统若只能把若干权利捆绑执行,响应就把必选项与成组可选项表现出来。它回答的是“这台服务器能为这个主体表达什么变化”。

MYRIGHTS 则给出当前登录用户的有效集合。它回答“身份匹配和本地合并结束后,执行服务器现在允许这个会话做什么”。

把三者压成一个绿色勾号会丢掉关键证据。规则回读成功,只证明声明状态已经写入;MYRIGHTS 证明一个会话此刻的计算结果;受保护操作被接受,才证明那项动作确实执行,但仍然不能证明凭据背后是哪一个人。

删除拿走一个理由,扣减才参与最后计算

DELETEACL mailbox fred 删除 fred 对应的那一对字段。如果 Fred 还从 support-team 或 anyone 得到 w,命令完全成功也不会消除写权限。

RFC 2086 还把以短横线开头的标识符留给 negative rights,RFC 4314 把含义说得更明确。-fred 上的 w 会在最终计算中扣掉 Fred 的写权限,即便另一个命中身份原本会把 w 加回来。negative entry 是计算的一部分;DELETEACL 只负责移除一条正向或负向条目。

但服务器并非必须支持 negative rights。客户端不能因为标准存在这种写法,就向用户承诺一个普遍有效的“拒绝优先”按钮。它必须先发现服务器能力,再验证有效结果。

两个短横线也不能混为一谈。SETACL 的权限参数写成 -w,表示从选定条目中移除 w;标识符写成 -fred,表示一个参与扣减计算的负向身份。前者编辑一行,后者改变计算输入。符号相似,权力层次不同。

权限被拆细,旧客户端没有被突然抛弃

最初的扩展用字母表示查看、读取、已读状态、其他标记写入、插入、投递、创建、删除和管理。部分字母覆盖过宽,尤其 c、d 对“删除邮件”与“删除整个邮箱”的边界产生实现分歧。

2005 年 12 月,RFC 4314 取代 RFC 2086,把操作拆开:k 控制创建子邮箱,x 控制删除或移动邮箱,t 控制给邮件加删除标记,e 控制真正清除邮件。旧的 c 和 d 仍以虚拟兼容权利存在,让旧客户端得到一个有定义但不够精细的投影,新服务器则可以执行更窄的权限。

这段迁移体现的是克制。标准没有假装部署中的软件能一夜更换,而是在新模型里缩小权力,以 RIGHTS= 宣告额外权利,同时维持旧实现可理解的视图。

RFC 4314 还要求能读写 ACL 的客户端保留自己不认识、又不允许用户编辑的权利。否则,旧界面读取一条包含新字母的记录,再只写回它认识的部分,就会悄悄删掉未知权限。可扩展性依靠的不是假装全部理解,而是对无知采取保守处理。

撤权还有一个时间边界

正确改变有效权限,也不保证一个已经选择邮箱的会话立刻采用新结果。RFC 4314 允许服务器在 SELECT 时缓存权限。完成 SETACL 或 DELETEACL 后,STORE、EXPUNGE 等已选择状态下的命令,可能要到重新选择邮箱后才体现变化。

每次命令都重新检查的服务器,可以更新 FLAGS,拒绝后续操作,或在读权限消失后关闭连接。但标准没有虚构一个跨所有会话同时生效的撤权瞬间;它指出了运营者必须测试的会话边界。

同一连接里的排序则可以确定。客户端即使把 SETACL 与 MYRIGHTS 流水发送,服务器也必须先完成修改,再计算后一个回答。协议能排序这一条连接的证据,却不能证明另一条连接缓存了什么,更不能保证图形界面怎样解释响应。

规则表本身也会泄露权力结构

ACL 不含邮件正文,也可能是敏感资料。它会暴露邮箱是否存在、哪些用户或群组存在、谁能管理它。RFC 2086 已经警告,无权的 GETACL 不得泄露受保护邮箱;RFC 4314 进一步要求,当请求者没有查看权限时,受限邮箱与不存在邮箱应表现一致。

后来的文档也不再把“能读邮件”当成“能看 ACL”的充分条件,因为规则表里的标识符本身就是安全信息。与此同时,ACL 协议并不自带加密。若未协商 STARTTLS、认证层隐私保护或其他保密机制,ACL 数据仍可能明文经过网络。

所以授权正确不等于传输保密。服务器可以准确回答谁能读邮箱,却仍需要另一层保护这个答案本身。

标准承认剩余部分必须留在本地

RFC 4314 没有掩饰缺陷:身份合并语义仍由实现决定,用户、群组和 anyone 共用一个命名空间,友好的通用界面很难完整呈现本地模型,协议也缺少文件系统那种普遍的所有者变更操作。

文档仍认为兼容修订值得做,因为 RFC 2086 已经存在于多种实现中。RFC 9051 后来定义 IMAP4rev2,并让已注册的 IMAP4rev1 扩展在没有特别冲突时继续适用。这是协议表面的连续性,不是“所有现行邮件服务都实现 ACL 或 negative rights”的证据。

留下来的原则很窄,却足够重要:IMAP 没有让一张中央规则表统治所有邮件服务器。它只把几个必须互通的问题标准化,让客户端区分声明条目、可表达的授予和执行者算出的有效权力。本地身份图和最终决定,仍由实际运行代码负责。

来源