#server #name #xous #resolution #inter-process #microkernel #id

xous-api-names

基于 Xous 微内核操作系统的进程间命名解析服务器

62 个版本

0.9.61 2024 年 6 月 26 日
0.9.59 2024 年 5 月 28 日
0.9.56 2024 年 2 月 6 日
0.9.54 2023 年 12 月 25 日
0.9.23 2022 年 11 月 26 日

#511认证 类别中

Download history 214/week @ 2024-05-01 153/week @ 2024-05-08 92/week @ 2024-05-15 221/week @ 2024-05-22 321/week @ 2024-05-29 98/week @ 2024-06-05 208/week @ 2024-06-12 51/week @ 2024-06-19 298/week @ 2024-06-26 252/week @ 2024-07-03 68/week @ 2024-07-10 120/week @ 2024-07-17 391/week @ 2024-07-24 255/week @ 2024-07-31 175/week @ 2024-08-07 67/week @ 2024-08-14

每月下载量 911 次
6 crates 中使用

MIT/Apache 协议

290KB
5.5K SLoC

Xous API:命名

xous-names 将明文服务器名称解析为 128 位随机分配的服务器 ID。它也是限制对服务访问的前端门卫,通过防止连接或可发现性(或者更准确地说,由于需要暴力破解随机分配数字的 128 位空间中的服务器 ID,因此可发现性本身就很困难)来阻止。

有关更多详细信息,请参阅 Xous 书籍。Xous 书籍应视为规范性文件;下面的规范是历史性的。

规范

服务器 ID(SIDs)被进程用来向服务器发送消息。因此,它是一个攻击面。此外,如果一个进程可以在服务器声称它之前伪造一个 SID,那么它就可以“成为”服务器。因此,保持 SID 为秘密是有帮助的。

在 Xous 中,SID 是一个 128 位的数字,除了两个例外,只有服务器本身和一个称为 xous-name-server 的预言者知道。

SIDs 从不向进程透露。进程使用描述性、人类可读的字符串名称连接到服务器。由于 SIDs 是随机数字,除了通过 xous-name-server 解析之外,没有其他方法可以将描述性字符串转换为 SID。

在引导时,启动了一个可信的进程集,这些进程形成了操作系统。在启动任何其他进程之前,这些进程必须在该命名空间中声明名称,以防止后续进程声明它们的名称。服务器还可以选择性地限制允许的连接总数,这实际上使得它们对在核心可信进程集启动后运行的较低信任代码不可达。在名称服务器上调用 trusted_init_done() 库调用将返回 true,如果所有具有连接限制的服务器都已完全填充了它们的连接。

随机SIDs的例外是 xous-name-serverxous-log-server (注意尾随空格)和 ticktimer-server。这三个是众所周知的名字,它们有定义的、固定的SID,以便所有进程都可以与它们通信;《code>xous-name-server 是必要的,因为它是解析进一步名称的机制;《code>xous-log-server 对于调试是必要的,这样就可以记录名称解析上游的bug。《code>xous-name-server 被选择是因为在DNS的上下文中,《code>name-server 已经有了一个含义。《code>ticktimer-server 对于在 xous-name-server 失败时实现确定性的定时延迟是必要的,同时也允许其他进程在初始化时等待一个固定的时间,直到名称注册的初始集发生。

打算接收消息的新进程使用 register_name 便利函数在 xous-names/src/lib.rs 文件中,按照以下程序。

  1. 它调用 register_name 并传递一个首选的ASCII名称字符串,限制为64个字符。它还指定服务器将允许多少个连接。None 在指定器上表示没有限制。

  2. xous-name-server 将借用内存返回给服务器,其中缓冲区已被响应字段替换。如果注册被确认,则 Registration 中的SID字段包含调用进程的分配SID。如果名称被确定为无效(可能是因为它已经被预留或注册),则返回错误代码。

  3. 如果注册被拒绝,服务器可以尝试通过重复步骤2-3,使用不同的ASCII名称字符串重新注册其SID。

想要向服务器发送消息的进程必须首先请求名称服务器代理与目标进程建立连接。它通常通过调用 request_conneciton_blocking 便利函数并使用服务器的注册名称来完成此操作。

  1. request_connection_blocking 使用最大64个字符的ASCII名称字符串。

  2. 便利函数创建一个 Lookup 消息,并将其借给名称服务器。

  3. xous-name-server 可以响应三种结果之一:A. 通过返回连接ID确认连接;B. 直接拒绝连接;或C. 包含请求认证的槽。

以下是处理的情况

A. 确认连接:xous-name-server 会使用 MessageSender.pid() 提取发送者的PID,并代表发送者调用 ConnectForProcess(PID,SID)。发送者可以使用CID作为 send_message() 的第一个参数。这是常见情况,许多服务器遵循此路径,例如请求访问 ticktimer 或其他公共服务。

否定拒绝:`xous-name-server`只简单地返回一条消息,表示请求被拒绝。当请求格式错误或不正确时,也是如此。不应泄露关于拒绝性质的信息。拒绝也会延迟到启动后的最近0.1秒间隔,以消除旁路通道并限制模糊测试请求。某些服务(如密钥服务器)仅限于启动时加载的一组受信任进程,因此它不应该被发现。

请求进行认证:`xous-name-server`以`success`设置为`false`响应,但`authenticate_request`设置为`true`。`pubkey_id`字段填充了用于认证的接受Ed25519公钥的ID,并在`challenge`字段中提供了一个256位的挑战非确定数。认证包括请求服务器证明它知道一个共享秘密,即Ed25519私钥。

在生成认证请求后,`xous-name-server`计算出对挑战的正确响应,并将其存储在带有时间戳的表中。

发送进程必须随后对`challenge`进行签名,并返回一个`Authenticate`消息,其结构与`Lookup`消息类似,但`response_to_challenge`字段已填写。它必须在`AUTHENTICATE_TIMEOUT`毫秒之前完成。服务器在收到`Authenticate`消息后,只需检查`response_to_challenge`是否与表中存储的任何响应匹配,如果匹配,则接受该进程为已认证。在表中出现冲突的加密可能性很小;然而,这种实现容易受到攻击者可能窃取响应并使用的攻击。话虽如此,如果攻击者已经在调用进程中达到这种控制水平,那么将存在更大的问题。

`AUTHENTICATE_TIMEOUT`字段用于给`xous-name-server`一个机会,随着时间的推移清理响应表,这样它就不会“泄漏”内存。

当前实现

当前实现是一个哈希表,将随机生成的名称与每个服务器为自己选择的名称列表匹配。目前,任何查找和连接到服务器的请求都将成功,直到服务器指定的连接限制(如果有),但钩子可以强制执行权限和拒绝连接,以及/或请求连接认证。

服务器名称是crate本地的,并且通过在创建服务器访问对象期间调用的库函数绑定。换句话说,没有全局服务器名称空间。

依赖关系

~2.5MB
~62K SLoC