问题以许可证的面目出现,但答案要从一份清单开始。一个 VPN 界面、它所驱动的 OpenVPN 引擎、一个 TLS 库和一个安装程序,可能分别适用四套不同的条款,而产品的外观丝毫不会告诉你哪个文件属于哪一套。按分发顺序逐一过一遍这些产物,等你把它交给有资格作答的人时,法律问题就窄得多了。每一步都会进一步收窄:分发了什么、修改了什么、各部分如何通信。

从安装程序写到磁盘上的内容开始

拿正式发布的安装程序或软件包,而不是开发用的检出副本,列出它在一台干净机器上放置的每个文件。记录界面、引擎和 TLS 库的版本,并注明引擎是独立的可执行文件,还是加载进同一进程的库。

最后这一点决定了后面的一切。通过套接字启动的独立可执行文件,与编译进单个二进制的代码所引出的问题并不相同;而一个只是把两者并排放在一起的安装程序,在任何一个方向上都算不上定论。捆绑是打包层面的决定,而程序之间的关系属于架构层面的决定。

把清单连同版本一并写下来,因为不同主版本之间的条款并不相同。

dpkg -L openvpn | head -n 40
openssl version -a

把界面和引擎分开

OpenVPN 的复制许可文件声明 GPL 第 2 版,并记录了对 OpenSSL 的链接例外——那是一项范围明确的特定许可,而不是可以随意混合条款的通用许可证。

留存随你的构建一起分发的许可证文本,而不是今天项目网站上的那一份。锁定较旧分支的发布版本,携带的是那个分支的文档。仓库页面的截图不能替代文件本身,因为你需要的是产物内部的那一份。把它存放在安装程序旁边,让这套材料保持完整。

然后如实描述集成方式:界面是把引擎作为子进程启动并走文本协议,还是链接一个库并交换内部结构?后一种安排比前一种更为紧密,而这正是审查者最先会问的区别。

记下你修改了哪些文件

被修改的源代码对分析的影响,超过任何打包细节。如果你给引擎打了补丁,补丁本身就是衍生作品,义务落在分发该结果的人身上。

记录每个补丁、它的目的,以及是否已提交上游;因为即使某个补丁从未离开你的仓库,只要你分发二进制文件,它仍是分发内容的一部分。

配置文件、主题和翻译通常与界面放在一起,但一个内嵌了引擎源代码字符串的翻译,恰好提醒人们:边界是按文件划分的,而不是按目录。保留上游发布版与你构建版之间的差异,这样需要时答案随手可得,而不必事后重建。当审计者问起改了什么时,这份差异也是最有用的一份材料。

单独核对 OpenSSL 版本

OpenSSL 3.0 及以后版本按 Apache License 2.0 分发,而更早的版本携带 OpenSSL/SSLeay 条款。这是两份义务不同的文档,而捆绑进来的引擎可能链接的是构建系统实际找到的那一个。

确认实际分发的版本,而不是构建脚本里写明的版本。

对 OpenVPN 的依赖并不会把对 OpenSSL 的每一处修改都变成 GPL 代码,链接例外也不会消除再分发该库所附带的其他义务。把这项例外当作更大分析中的一个条款,并把 TLS 库自身的声明与其他一切一并记录。

把证据包整理出来

证据包包含四部分:带版本的文件清单、集成方式说明、带差异的修改清单,以及按分发原样保存的许可证文本。再加上你分发的声明文件;如果你的义务要求提供源码获取途径,也要写上提供方式。

让证据包由同一个人负责,这样任何一次发布都无法在不带它的情况下出门。

这些都不构成对法律问题的裁决,而这正是重点:它给有资格的审查者的是事实,而不是某人凭记忆拼出的摘要。厂商的营销说明不是其架构的证据,你自己的猜测同样不是证据。

相关文章