<chapt>Debian 的安全机制

<sect id="debian-sec-team">Debian 安全小组

<p>Debian 有一个由五名成员和两位秘书组成的安全小组, 来处理 <em>stable</em> 发行版的安全问题. 
处理安全问题意味着他们要跟踪记录软件出现的问题(查看论坛譬如 bugtraq, 或 vuln-dev)
并确定 stable 版是否受其影响.

<p>同时, Debian 安全小组, 也是与上游开发者或组织进行问题协调的接触点, 
如类似 CERT 可能有广泛影响的供应商. 也就是说, 当问题不在 Debian 时, 有两种方法与安全小组取得联系:

<list>

<item><url id="mailto:team@security.debian.org"
name="team@security.debian.org"> 其唯一的阅读者就是安全小组的成员.

<item><url id="mailto:security@debian.org" name="security@debian.org">
阅读者是 Debian 所有的开发者(包括安全小组). 发送到这个列表的邮件将不会在互联网上公布(这不是一个公开的邮件列表).

</list>

<p>敏感问题应当发送到第一个地址, 并且在某些情况下, 应当使用 Debian 安全小组的公钥加密
(key ID 363CCD95).

<p>一旦一个可能的问题被安全小组接受, 将会被调查其是否对 <em>stable</em> 版造成影响, 如果是, 
将会做一个基于源代码的修复. 这修复有时包括上游制作的移植补丁(它通常比 Debian 发行的要高几个版本). 
修复通过测试后, 将会准备新的软件包, 并在 <url
id="security.debian.org"> 站点上发布, 这样就可以通过 <prgn>apt</prgn> 获取(见 <ref id="security-update">). 
同时, 将会在web站点上发布<em>Debian 安全公告</em>(DSA), 并将其发送给包括 <url
id="lists.debian.org/debian-security-announce"
name="debian-security-announce"> 和 bugtraq 在内的邮件列表.

<p>其它有关 Debian 安全小组的常见问题可以参阅<ref id="debian-sec-team-faq">.


<sect id="dsa">Debian 安全公告

<p>每当发现一个 Debian 软件包的安全漏洞时, 就会发布 Debian 安全公告. 
公告由安全小组成员之一签署, 其包括版本影响信息和其 MD5sums. 此信息是:

<list>
<item>问题软件的版本号.
<item>问题类型.
<item>是会被远程攻击还是本地.
<item>软件包的简短描述.
<item>问题描述.
<item>攻击描述.
<item>修复描述.
</list>


<p>DSAs 将在 <url id="http://www.debian.org/"
name="Debian 主服务器的首页">, 和 <url
id="http://www.debian.org/security/" name="Debian s安全页面">公布. 
只有在网站重建时(每天一次)才发生这种情况, 因此它们并不能被及时公布. 
更好的途径是通过 debian-security-announce 邮件列表来获取公告.

<p>然而感兴趣的用户可以, (需要通过一些 Debian 相关端口来完成)使用 RDF 频道去自动下载 DSAs 到他们的计算机. 
一些应用程序，譬如 <prgn>Evolution</prgn> (电子邮件客户和个人信息助理) 
和 <prgn>Multiticker</prgn> (一个GNOME附属程序)，可以用来自动获取公告. 
RDF 频道可以由 <url id="http://www.debian.org/security/dsa.rdf"> 处获得.

<p>在网站上公布的 DSAs 也许在发送到公共邮件列表之后更新. 
一次普通的更新将会添加对安全漏洞数据库交叉参考. 
其它语言的译文<footnote>现在已经有超过10种不同语言的翻译</footnote>不会发送到安全邮件列表, 而是直接张帖在网站上. 


<sect1 id="crossreference">漏洞的交叉参考

<p>Debian 提供一个包括所有自1998年以来所有发布公告的可用参照在内的完整的 <url
id="http://www.debian.org/security/crossreferences"
name="crossreferenced table"> . 这个表是 <url
id="http://cve.mitre.org/cve/refs/refmap/source-DEBIAN.html"
name="reference map available at CVE">的一个补充. 

<P>您会将会注意到这个表如 CVE 一样为 url id="http://www.securityfocus.com/bid"
name="Bugtraq">, <url id="http://www.cert.org/advisories/" name="CERT/CC Advisories">
和 <url id="http://www.kb.cert.org/vuls" name="US-CERT Vulnerability
Notes Database">提供了数据库参考. 这些参考方便使用, 只有CVE参考进行周期性的审核和引用. 
这个特性是2002年6月添加到网站的.

<p>添加交叉参考到漏洞数据库的一个优点是:

<list>
<item>使 Debian 的用户更加容易查看和跟踪(已发布的)已经由 Debian 解决了的公告问题. 

<item>系统管理员发现更多的漏洞以及其对交叉参考的影响.

<item>这些信息也可用于漏洞扫描器的交叉检测输出, 其包括参考 CVE 删除错误信息
(参见 <ref id="vulnasses-false-positive">).

</list>
</sect1>

<sect1 id="cve-compatible">CVE 兼容性

<P>Debian 安全公告于2004 年2月24 日
Debian Security Advisories were <url
id="http://www.debian.org/security/CVE-certificate.jpg" name="宣布通过CVE兼容认证">
<footnote>完全通过 CVE 的<url
id="http://cve.mitre.org/compatible/phase2/SPI_Debian.html"
name="capability questionnaire"></footnote>.

<p>Debian 的开发者理解提供准确及时的有关 Debian 发行版安全信息的需求, 以及允许有户处理最新安全漏洞的风险. CVE 可以使我们能够为用户开发 <url
id="http://www.cve.mitre.org/compatible/enterprise.html"
name="启用 CVE的安全管理过程"> 提供规范的参考.

<p><url id="http://cve.mitre.org" name="Common Vulnerabilities and
Exposures (CVE)"> 项目由 MITRE Corporation 负责维护, 并提供漏洞和安全问题的规范化名称列表.

<P>Debian 相信为用户提供影响 Debian 发行版的安全问题的附加信息是非常重要的. 在公告中 CVE 名称有助于用户了解漏洞与某个 Debian 安全更新的关系, 这有助于减少花费在处理影响我们用户的漏洞上的时间. 同时, 也使得对于部署了支持 CVE 的安全工具的环境的安全问题的管理变得简单 - 譬如基于网络或主机的入侵检测系统, 或漏洞评估工具, 不管它是不是基于 Debian 发行版的. 


<p>Debian 从2002 年6月开始在 DSA 中提供 CVE 名称的, 现在为所有1998年9月以后发布的 DSA 提供 CVE 名称. 所有的公告,以及与新的安全漏洞相关的声明, 都能从 Debian 的 web 站点上获取, 它包含对应的 CVE 名称, 如果当时已经公布了的话. 带有CVE名称的公告可以通过 <url id="http://search.debian.org/" name="搜索引擎"> 直接搜索.

<p>想要查询某个特定 CVE 的有户可以通过使用 debian.org 上提供的搜索引擎查询到与该 CVE 名称相关的公告(英文的或翻译成其它语种的). 每次可以使用具体的名称(比如 advisory <url
id="http://search.debian.org/?q=advisory+%22CAN-2002-0001%22&amp;ps=50&amp;o=1&amp;m=all"
name="CAN-2002-0001">) 或名称的一部分(如查询2002年所有的公告就搜索 <url
id="http://search.debian.org/?q=advisory+%22CAN-2002%22&amp;ps=50&amp;o=1&amp;m=all"
name="CAN-2002">). 注意, 当您检索公告时, 应到同时输入单词  advisory 和 CVE 名称, 这样就可以只检索安全公告.


<p>在某些情况下您也许在发布的公告中不能找到指定的 CVE 名称, 或许因为:

<list>
   <item>这个漏洞对于 Debian 没有影响. .
   <item>仍然还没有针对这个漏洞的安全公告.(安全问题也许已经作为 <url
   id="http://bugs.debian.org/cgi-bin/pkgreport.cgi?tag=security"
   name="安全问题">被提交了,但是修复还没有测试和上载)
   <item>安全公告在对该漏洞分配CVE名称之前发布(在网站上查找更新)
</list>
</sect1>

</sect>

<sect>Debian 安全构建机制

<p>因为当前的 Debian 支持大多数的平台, 管理员有时想知道是不是某一平台的安全更新比其它平台需要更多的时间. 
事实上除了极罕见的情况外, 所有平台都是同事更新的.

<p>以前, 安全更新是手工完成的, 但是现在不是了(就如 Anthony Towns 
在2002年6月8日发给 debian-devel-announce 邮件列表的 
<url id="http://lists.debian.org/debian-devel-announce/2002/debian-devel-announce-200206/msg00002.html" name="一封邮件">
中描述的那样.)

<p>软件包是由安全小组完成上载的(并在完成上载后十五分钟内附带上载到 <url
id="security.debian.org:/org/security.debian.org/queue/unchecked"> 或
<url id="ftp://security.debian.org/pub/SecurityUploadQueue">
一个用于检查签名的补丁, 完成后, 它们将被加入自动构建清单(这不再是每日的事务).

因此,软件包可以自动在它们被上载后的三十分钟货一个小时内完成基于<em>各个</em>平台的构建. 
然而, 安全更新与平时的软件维护者完成的上载稍有不同, 在某些情况下, 在公布以前, 
需要等待进一步测试, 得到测试报告, 或者需要等待一个周, 或者更久的时间, 
以避免与软件的原始开发者修正这一错误发生冲突. 

<p>因而, 安全更新工作包括一下步骤(称作 <em>"Accepted-Autobuilding"</em>):

<list>

<item>有人发现了安全问题.
     
<item>某个人修正该问题，并上载到 security.debian.org 的 incoming 区
	(<em>某个人</em> 通常是安全小组成员, 但也可能是一个以前与安全小组有过联系的软件维护者完成修正). 
	修改日志包括根据目标版本 <em>testing-security</em>
      或 <em>stable-security</em>.

<item>提交由一个 Debian 系统完成检查和处理, 然后将其转移到 queue/accepted, 
       并在 buildds 上通告. 这些文件可由安全小组和(间接的) buildds 访问.

<item>Security-enabled buildds 对源码包进行整理, 打包, 然后将日志发送给安全小组.

<item>安全小组对日志做出回应, 最新构建的软件包将被上载到 queue/unchecked, 
       在这里它们由 Debian 系统统一处理, 然后转移到 queue/accepted.

<item> 当安全小组发现源码包可以接受时(即,它可以在各种平台正确的构建, 
       并且修复了安全漏洞, 而自身不会产生新的问题), 他们将会运行一个脚本来完成:

<list>
<item>软件包安装到安全归档区.

<item>用通常的方式(<prgn>dpkg-scanpackages</prgn>,
<prgn>dpkg-scansources</prgn>...)更新软件包, 源代码并在 security.debian.org 上发布文件

<item>设定安全小组完成的模板通告.

<item>(随意的)将软件包转移到对应的 proposed-updates, 这样就可以尽快的进入真正的归档区.

</list>

</list>

<p>早先由手工完成的这些工作, 被测试后进入处于冻结阶段的 Debian 3.0 woody(2002年7月). 
感谢这种机制, 使得安全小组可以在不到一天的时间内为所有的(大约二十种)平台更新 apache 和 OpenSSH.

<sect1>安全更新的开发指南

<p>此邮件是由 Wichert Akkerman 寄发了到 <url
id="http://lists.debian.org/debian-devel-announce/2002/debian-devel-announce-200206/msg00004.html"
name="Debian-devel-announce 邮件列表"> 的, 描述了 Debian 开发者在处理他们的软件包中的安全问题时所做的工作. 
其发表的目的即是为了开发者的利益, 同时也是为了用户更好的理解Debian中对于安全问题的处理.

<p>请注意此处的更新参考源自<url id="http://www.debian.org/doc/manuals/developers-reference/ch-pkgs.en.html#bug-security" name="Debian 开发者参考手册">
不久将被删除.

<sect2>安全小组的协调工作

<p>如果开发者获知在他的或别人的软件包里存在一个安全问题, 则总应当与安全小组取得联系(通过team@security.debian.org). 
他们将跟踪记录未解决的安全问题, 可以帮助维护者解决安全问题, 或者由他们自己解决, 并负责发送安全公告和维护security.debian.org.

<p>请注意只有发行版才有安全公告, 测试版(testing), 非稳定版(unstable) (详见 <ref id="sec-unstable">), 
或旧的发行版(详见<ref id="sec-older">) 是没有的.

<sect2>获取安全问题

<p>开发者有几种获取安全问题的途径:

<list>
<item>关注公共论坛(邮件列表、网站等等.):
<item>某人提交的问题报告(应当由开发者使用或添加<em>安全</em>标签)
<item>通过私有邮件获取的信息.
</list>

<p>其中源自第一二项的信息是公开的, 并且需要尽快修补. 源自最后一项的信息可能不是公开的, 
有几个可能的选择来处理这类问题:

<list>

<item>如果只是一些细微的问题(如不安全的临时文件)则没有必要对这个问题保密, 制作修补程序, 并发布.

<item>如果问题很严重(可用于远程攻击, 并可获取 root 权限)则最好告知其它开发者, 协调解决.
 安全小组与各种组织和个人保持着联系,并关注他们.

</list>

<p>不管何种途径, 如果某人要求不应向外透露其报告的问题, 则应当尊重其选择, 
当然告知安全小组则明显不在此列(开发者应当确保其告诉安全小组的信息不会被泄露).

<p>请注意如果需要开发者可以不把修复上载到 unstable区(或其它地方), 因为 unstable 的更新日志是公开的.

<p>即使被请求/必须保密, 仍有两种情况需要公布这些信息:问题长期为人所知,或信息已经公开化.

<sect2>构建软件包

<p>为修补安全问题构建一个软件包的最重要的原则是尽可能少的产生变动. 
人们通常依靠于发行版已构建的软件包, 因此其任何变动都有可能造成系统崩溃, 
特别是对于库包: 开发者必须确保其没有修改 API 或 ABI, 即使是很细微的变动.

<p>这意味着, 更新为一个新的上游版本并不是一个好的解决方法, 相反移植(backport)应该是更好的选择. 
通常如果需要, 上游维护者是愿意提供帮助的, 即使不是 Debian 安全小组也能提供帮助.

<p>在某些情况下是不可能通过移植来解决安全问题的, 例如大部分的原代码被修改或重写. 
如果是这种情况, 则可能必须转向一个新的上游版本, 但是这必须有安全小组来预先协调.

<p>与此相关的其它几个重要方面: 开发者必须对每次改动都进行测试. 
如果是 exploit, 则开发者应当尝试确认是否只能在未打补丁的软件包上成功, 而在修补了的软件包上则不行.
开发者还应当测试一下一些常用的操作，有时候，安全修复会影响到软件的基本功能.

<p>最后, 开发者应当记住几条技术方面的事项:

<list>
<item> 确保在 debian/changelog 中分类正确. 对于稳定版是 stable-security, 对于测试版则是 testing-security. 
不要针对 &lt;codename&gt;-proposed-updates.

<item> 确保使用了适当的版本号. 其必须比当前的要高. 但比最新发行的要低. 
  对于测试版, 这意味着其没有比 unstable 高的版本. 如果根本不存在这个软件(例如 testing 和 unstable 版本相同),
  首先上载一个新版本到 unstable 区.

<item> 如果你的软件包包含二进制部分,不要仅仅上载源码. buildd 机制不会自动构建它们.

<item> 确保你是在一个干净的系统上编译软件包, 即只安装了源于您基于的发行版的软件包. 
  如果您自己没有这样的系统, 您可以尝试一下 debian.org machine(详见 http://db.debian.org/machines.cgi) 
  或设置一个 chroot(在这种情况下 pbuilder 和 debootstrap非常有用).

</list>

<sect2>上载安全修复文件

<p>在开发开发者完成生成并测试了新的软件包后, 就需要将其上载, 这样就可以被安装到归档区中. 应上载到的安全上载区是
ftp://security.debian.org/pub/SecurityUploadQueue/ .

<p>一旦安全队列中的一个上载被接受, 软件包将自动完成基于所有平台的构建, 并存储安全小组的确认.

<p>等待接受或确认的上载只能由安全小组访问. 这是必须的, 因为这也许是对无法被透露的安全问题的修补.

<p>如果安全小组的成员接受了一个软件包, 其将被安装到 security.debian.org 并在 ftp-master 或 non-US 归档区进行适当的 
&lt;codename&gt;-proposed-updates .

<sect2>安全公告

<p>安全公告由安全小组撰写和张贴. 但是他们也不介意有维护者为他们提供(一部分)文本. 在安全公告中应当提供的信息请参阅<ref id="dsa">.

<sect id="deb-pack-sign">Debian 中对软件包签字

<p>本部分也可以"如何安全升级/更新您的Deian GNU/Linux系统"冠名, 
它基本上应该作为一个独立的部分因为它是安全机制中很重要的一部分. 
软件包签名是为避免镜象中发布的软件包被篡改和下载被中间攻击很重要的一环. 
自动软件更新是一个很重要的特性, 但是移除在更新期间有助于木马分发和攻陷系统的威胁也很重要
<footnote>
<p>自动升级问题已经困扰了一些操作系统如
<url name="Mac OS X 软件升级漏洞"
id="http://www.cunap.com/~hardingr/projects/osx/exploit.html">.
<p>FIXME: 可能 IE 处理证书链漏洞已经开始影响 Microsoft Windows 的安全更新.
</footnote>


<p>就象现在(2003年 2月) Debian 并未为发行版提供签名的软件包, 并且 woody 发行版(3.0)也未继承此特性. 
对于单个的软件包在下一个发行版(<em>sarge</em>)中将会, 有希望, 也许, 能够得到解决.

<p>这个问题在V. Alex Brennen提供的
<url id="http://www.cryptnet.net/fdp/crypto/strong_distro.html" name="Strong
Distribution HOWTO"> 中有更详细的描述.

<sect1>软件包签名检测计划

<p>当前使用 <prgn>apt</prgn> 进行软件包签名检测的计划是:

<list>
<item>发行文件包含 Packages.gz(其内容为软件包的md5sum)的md5sum并被签名. 签名说明是个可信任的源.

<item>被签名的发行文件可以通过 'apt-get update' 下载并和 Packages.gz 放在一起.

<item>当安装软件包时,首先是下载,然后生成 md5sum.

<item>检测签名的发行件(signature ok),从中抽取 Packages.gz 的 md5sum 
生成 Packages.gz 的 checksum 然后(如果ok)从中提取下载软件包的 md5sum.

<item>如果下载软件的 md5sum 与 Packages.gz 中的相同, 软件包将会被安装, 
否则管理员会得到一个警告而软件包则被留在 cache 中(由管理员来决定是否安装), 
如果软件包不在 Packages.gz 中, 管理员可以配置系统只安装检测过的软件包, 而对于其它的软件包拒绝安装.
</list>

<p>下边的 MD5 sums <prgn>apt</prgn> 可以完成对于源自某个发行版的单个的软件包的校检. 这与对每个软件包签名相比不太灵活, 
也许会与这个计划结合(参见下面).

<p>当前, 在 apt 0.6 中<url
id="http://lists.debian.org/debian-devel/2003/debian-devel-200312/msg01986.html
" name="完全提供"> 了这个方案, 这是一个
<em>实验版本</em> 发布. 其改变是基于实验版本提供的用于  <prgn>apt</prgn> (可由 <url
id="http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=203741" name="Bug
#203741">处获取) 的补丁. 请将其检出, 并为 BTS 提供用于将此包含到主发行版中的信息, 因为它仍然需要大量的测试.

<P>注意, 使用实验版的 apt 并不需要特别的设置, 除非您使用的是 non-Debian 的源, 这时 apt-get 则需要一些而外的设置.
可以通过在 non-Debian 源中提供 Release 和 Release.gpg 来避免这中情况. Release 文件可由<prgn>apt-ftparchive</prgn>(apt-utils 0.5.0或更高版本中提供)生成
Release.gpg 文件仅是一个附加签名. 
下边简单的步骤可以生成这两个文件:

<example>
$ rm -f dists/unstable/Release
$ apt-ftparchive release dists/unstable > dists/unstable/Release
$ gpg --sign -ba -o dists/unstable/Release.gpg dists/unstable/Release
</example>

<p><prgn>apt-key</prgn> 为 apt 的 keyring 添加了新的 key, 默认只包括当前 Debian 归档区的签名 key.


<p>在Debian]中的软件包签名已经被讨论了相当一段时间了, 更多信息参见:
<url id="http://www.debian.org/News/weekly/2001/8/"> 和
<url id="http://www.debian.org/News/weekly/2000/11/">.

<sect1 id="check-releases">发行版检查

<p>如果您现在就想使用附加的安全检测, 而又不愿使用实验版的 apt(虽然我门非常希望对其进行检测),
则可以使用 Anthony Towns 提供的下边这个脚本. 此脚本可以自动完成一些新的安全检测, 
使得用户可以确认其下载的软件与 Debian 发行的相匹配. 这样就阻止了 Debian 开发者不负责的
通过提供上载到主归档, 或者镜象区, 的软件破坏别人的系统, 这与 Debian, 或其镜象提供带有已知漏洞的过期 unstable 拷贝不同.

<p>示例代码，将其命名为 <prgn>apt-check-sigs</prgn>, 可以通过下边的方法使用:
<example>
# apt-get update
# apt-check-sigs
(...results...)
# apt-get dist-upgrade
</example>

<p>首先, 您需要:

<list>

<item>获取用于对发行文件签名的公钥,
<url id="http://ftp-master.debian.org/ziyi_key_2003.asc"> 并将其添加到
<file>~/.gnupg/trustedkeys.gpg</file> (<prgn>gpgv</prgn> 默认使用的文件).
<example>
  gpg --no-default-keyring --keyring trustedkeys.gpg --import ziyi_key_2003.asc
</example>

<item>删除 <file>/etc/apt/sources.list</file> 中所有没有正常使用 "dists" 的行,
或者修改脚本,以便对它们有效.

<item>准备忽略 Debian 安全更新未含有签名的发行文件, 以及在发行文件中(也)没有正确的 checksums 的源码文件.

<item>准备用正确的公钥检查对应的源码.

</list>

<p>这是 <prgn>apt-check-sigs</prgn> 的示例代码，最新的版本可从 <url
id="http://people.debian.org/~ajt/apt-check-sigs"> 处获取.
此代码当前为 beta 版, 更多信息参见
<url id="http://lists.debian.org/debian-devel/2002/debian-devel-200207/msg00421.html">.

<example>
#!/bin/bash

# Copyright (c) 2001 Anthony Towns &lt;ajt@debian.org&gt;
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

rm -rf /tmp/apt-release-check
mkdir /tmp/apt-release-check || exit 1
cd /tmp/apt-release-check

>OK
>MISSING
>NOCHECK
>BAD

arch=`dpkg --print-installation-architecture`

am_root () {
        [ `id -u` -eq 0 ]
}

get_md5sumsize () {
        cat "$1" | awk '/^MD5Sum:/,/^SHA1:/' | 
          MYARG="$2" perl -ne '@f = split /\s+/; if ($f[3] eq $ENV{"MYARG"}) {
print "$f[1] $f[2]\n"; exit(0); }'
}

checkit () {
        local FILE="$1"
        local LOOKUP="$2"

        Y="`get_md5sumsize Release "$LOOKUP"`"
        Y="`echo "$Y" | sed 's/^ *//;s/  */ /g'`"

        if [ ! -e "/var/lib/apt/lists/$FILE" ]; then
                if [ "$Y" = "" ]; then
                        # No file, but not needed anyway
                        echo "OK"
                        return
                fi
                echo "$FILE" >>MISSING
                echo "MISSING $Y"
                return
        fi
        if [ "$Y" = "" ]; then
                echo "$FILE" >>NOCHECK
                echo "NOCHECK"
                return
        fi
        X="`md5sum < /var/lib/apt/lists/$FILE | cut -d\  -f1` `wc -c < /var/lib
/apt/lists/$FILE`"
        X="`echo "$X" | sed 's/^ *//;s/  */ /g'`"
        if [ "$X" != "$Y" ]; then
                echo "$FILE" >>BAD
                echo "BAD"
                return
        fi
        echo "$FILE" >>OK
        echo "OK"
}

echo
echo "Checking sources in /etc/apt/sources.list:"
echo "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
echo
(echo "You should take care to ensure that the distributions you're downloading"
echo "are the ones you think you are downloading, and that they are as up to"
echo "date as you would expect (testing and unstable should be no more than"
echo "two or three days out of date, stable-updates no more than a few weeks"
echo "or a month)."
) | fmt
echo

cat /etc/apt/sources.list | 
  sed 's/^ *//' | grep '^[^#]' |
  while read ty url dist comps; do
        if [ "${url%%:*}" = "http" -o "${url%%:*}" = "ftp" ]; then
                baseurl="${url#*://}"
        else
                continue
        fi

        echo "Source: ${ty} ${url} ${dist} ${comps}"

        rm -f Release Release.gpg
        lynx -reload -dump "${url}/dists/${dist}/Release" >/dev/null 2>&1
        wget -q -O Release "${url}/dists/${dist}/Release"

        if ! grep -q '^' Release; then
                echo "  * NO TOP-LEVEL Release FILE"
                >Release
        else
                origline=`sed -n 's/^Origin: *//p' Release | head -1`
                lablline=`sed -n 's/^Label: *//p' Release | head -1`
                suitline=`sed -n 's/^Suite: *//p' Release | head -1`
                codeline=`sed -n 's/^Codename: *//p' Release | head -1`
                dateline=`grep "^Date:" Release | head -1`
                dscrline=`grep "^Description:" Release | head -1`
                echo "  o Origin: $origline/$lablline"
                echo "  o Suite: $suitline/$codeline"
                echo "  o $dateline"
                echo "  o $dscrline"

                if [ "${dist%%/*}" != "$suitline" -a "${dist%%/*}" != "$codeline" ]; then
                        echo "  * WARNING: asked for $dist, got $suitline/$codeline"
                fi

                lynx -reload -dump "${url}/dists/${dist}/Release.gpg" >/dev/null 2>&1
                wget -q -O Release.gpg "${url}/dists/${dist}/Release.gpg"

                gpgv --status-fd 3 Release.gpg Release 3>&1 >/dev/null 2>&1 | sed -n "s/^\[GNUPG:\] //p" | (okay=0; err=""; while read gpgcode rest; do
                        if [ "$gpgcode" = "GOODSIG" ]; then
                            if [ "$err" != "" ]; then
                                echo "  * Signed by ${err# } key: ${rest#* }"
                            else
                                echo "  o Signed by: ${rest#* }"
                                okay=1
                            fi
                            err=""
                        elif [ "$gpgcode" = "BADSIG" ]; then
                            echo "  * BAD SIGNATURE BY: ${rest#* }"
                            err=""
                        elif [ "$gpgcode" = "ERRSIG" ]; then
                            echo "  * COULDN'T CHECK SIGNATURE BY KEYID: ${rest %% *}"
                            err=""
                        elif [ "$gpgcode" = "SIGREVOKED" ]; then
                            err="$err REVOKED"
                        elif [ "$gpgcode" = "SIGEXPIRED" ]; then
                            err="$err EXPIRED"
                        fi
                    done
                    if [ "$okay" != 1 ]; then
                        echo "  * NO VALID SIGNATURE"
                        >Release
                    fi)
        fi
        okaycomps=""
        for comp in $comps; do
                if [ "$ty" = "deb" ]; then
                        X=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/binary-${arch}/Release" | sed 's,//*,_,g'`" "${comp}/binary-${arch}/Release")
                        Y=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/binary-${arch}/Packages" | sed 's,//*,_,g'`" "${comp}/binary-${arch}/Packages")
                        if [ "$X $Y" = "OK OK" ]; then
                                okaycomps="$okaycomps $comp"
                        else
                                echo "  * PROBLEMS WITH $comp ($X, $Y)"
                        fi
                elif [ "$ty" = "deb-src" ]; then
                        X=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/source/Release" | sed 's,//*,_,g'`" "${comp}/source/Release")
                        Y=$(checkit "`echo "${baseurl}/dists/${dist}/${comp}/source/Sources" | sed 's,//*,_,g'`" "${comp}/source/Sources")
                        if [ "$X $Y" = "OK OK" ]; then
                                okaycomps="$okaycomps $comp"
                        else
                                echo "  * PROBLEMS WITH component $comp ($X, $Y)"
                        fi
                fi
        done
        [ "$okaycomps" = "" ] || echo "  o Okay:$okaycomps"
        echo
  done

echo "Results"
echo "~~~~~~~"
echo

allokay=true

cd /tmp/apt-release-check
diff <(cat BAD MISSING NOCHECK OK | sort) <(cd /var/lib/apt/lists && find . -type f -maxdepth 1 | sed 's,^\./,,g' | grep '_' | sort) | sed -n 's/^> //p' >UNVALIDATED

cd /tmp/apt-release-check
if grep -q ^ UNVALIDATED; then
    allokay=false
    (echo "The following files in /var/lib/apt/lists have not been validated."
    echo "This could turn out to be a harmless indication that this script"
    echo "is buggy or out of date, or it could let trojaned packages get onto"
    echo "your system."
    ) | fmt
    echo
    sed 's/^/    /' < UNVALIDATED
    echo
fi

if grep -q ^ BAD; then
    allokay=false
    (echo "The contents of the following files in /var/lib/apt/lists does not"
    echo "match what was expected. This may mean these sources are out of date,"
    echo "that the archive is having problems, or that someone is actively"
    echo "using your mirror to distribute trojans."
    if am_root; then 
        echo "The files have been renamed to have the extension .FAILED and"
        echo "will be ignored by apt."
        cat BAD | while read a; do
            mv /var/lib/apt/lists/$a /var/lib/apt/lists/${a}.FAILED
        done
    fi) | fmt
    echo
    sed 's/^/    /' < BAD
    echo
fi

if grep -q ^ MISSING; then
    allokay=false
    (echo "The following files from /var/lib/apt/lists were missing. This"
    echo "may cause you to miss out on updates to some vulnerable packages."
    ) | fmt
    echo
    sed 's/^/    /' < MISSING
    echo
fi

if grep -q ^ NOCHECK; then
    allokay=false
    (echo "The contents of the following files in /var/lib/apt/lists could not"
    echo "be validated due to the lack of a signed Release file, or the lack"
    echo "of an appropriate entry in a signed Release file. This probably"
    echo "means that the maintainers of these sources are slack, but may mean"
    echo "these sources are being actively used to distribute trojans."
    if am_root; then 
        echo "The files have been renamed to have the extension .FAILED and"
        echo "will be ignored by apt."
        cat NOCHECK | while read a; do
            mv /var/lib/apt/lists/$a /var/lib/apt/lists/${a}.FAILED
        done
    fi) | fmt
    echo
    sed 's/^/    /' < NOCHECK
    echo
fi

if $allokay; then
    echo 'Everything seems okay!'
    echo
fi

rm -rf /tmp/apt-release-check
</example>

<p>You might need to apply the following patch for <em>sid</em> since
<prgn>md5sum</prgn> adds an '-' after the sum when the input is stdin:

<example>
@@ -37,7 +37,7 @@
        local LOOKUP="$2"

        Y="`get_md5sumsize Release "$LOOKUP"`"
-       Y="`echo "$Y" | sed 's/^ *//;s/  */ /g'`"
+       Y="`echo "$Y" | sed 's/-//;s/^ *//;s/  */ /g'`"

        if [ ! -e "/var/lib/apt/lists/$FILE" ]; then
                if [ "$Y" = "" ]; then
@@ -55,7 +55,7 @@
                return
        fi
        X="`md5sum < /var/lib/apt/lists/$FILE` `wc -c < /var/lib/apt/lists/$FILE`"
-       X="`echo "$X" | sed 's/^ *//;s/  */ /g'`"
+       X="`echo "$X" | sed 's/-//;s/^ *//;s/  */ /g'`"
        if [ "$X" != "$Y" ]; then
                echo "$FILE" >>BAD
                echo "BAD"
</example>
<sect1>可供选种的软包签名方案

<p>这种附加签名方案是, 当其不再为其它现存软件包文件所参考时, 允许被检查, 甚至以前没有提供过软件包的第三方软件也允许在 Debian 中使用, 但这不是缺省的方案.

<p>这份软件包签名方案, 可以通过使用 <package>debsig-verify</package> 和 <package>debsigs</package> 来完成. 这两个软件包可以签名和校验包含在 .deb 中的自身签名. Debian 已经据有有完成这项工作的实力, 但是实施策略和工具只会在下一个发行版中提供. 

<p>最新的 dpkg 版本(从1.9.21开始)已经加入了提供这个功能的 <url
id="http://lists.debian.org/debian-dpkg/2001/debian-dpkg-200103/msg00024.html"
name="补丁">, 只要您安装了 <package>debsig-verify</package>.

<p>注: 当前 <file>/etc/dpkg/dpkg.cfg</file> 引入 "no-debsig" 为缺省值.

<p>注2: 来自开发者的签名署名当它们进入软包的时候被剥离, 因为当前首选的方法还是使用前边描述的那种方法.
