MSYS / Cygwin使用什么机制来模拟Unix域套接字?

时间:2014-04-15 14:03:19

标签: c# sockets cygwin msys unix-socket

我正在尝试编写(在C#中)一个软件,该软件与使用MSYS构建的另一个软件(MSYS仿真的)Unix域套接字进行通信。我已经了解到“套接字服务器”(我不清楚正确的术语是什么)会创建一个包含以下内容的临时文件:

!<socket >59108 282F93E1-9E2D051A-46B57EFC-64A1852F

59108对应于TCP端口,“套接字服务器”正在环回接口上侦听。使用数据包捕获工具,我已经能够确定“套接字客户端”连接到此端口,并通过环回接口交换信息。

我在我的软件中复制了这种行为,“套接字客户端”连接到我的侦听端口,但没有传输任何信息。我相信这里有另一个步骤,一个很可能涉及“套接字”文件中的GUID,但我一直无法确定它是什么。如何触发客户端的通信需要做什么?

似乎MSYS正在使用Cygwin的机制,它涉及一个命名事件,即(可能是?)由“服务器”创建,并由“服务器”发出信号(显然),但我对实现的天真尝试没有似乎工作正常。

我找到了an email written by Conrad Scott,它描述了“握手”过程中的各种缺点,并提出了据称解决它们的补丁。在这封电子邮件中,Conrad稍微描述了所使用的过程,他指出实际上有两个事件,一个由“服务器”管理,另一个由“客户端”管理。我已经使用API Monitor寻找对CreateEvent()的调用,虽然有几个,但我找不到一个看似“吸烟枪”的东西。对CreateSemaphore()也没有任何有趣的调用,所以似乎Conrad的补丁从未被应用过(或者,至少,它是在MSYS分叉Cygwin后的某个时候应用的。)

3 个答案:

答案 0 :(得分:3)

至少对于cygwin我现在可以回答你的问题:我刚刚使用MFC实现了一个兼容cygwin的套接字服务器。我是通过查看cygwin来源做到的。 似乎甚至没有事件。所以你提到的补丁似乎没有实现。

所有这一切都是:

1。)创建套接字文件,GUID(&#34;共享密钥&#34;)只是随机数。 2.)文件必须有&#34; system&#34;属性。如果它在NTFS上,那么cygwin代码会做一些奇怪的权限,但是没有考虑过。 3.)使用套接字文件中指示的端口创建localhost上的网络套接字。

那么,当客户端连接到套接字(通过TCP / IP)时:

4.)它首先将4个随机数发送给服务器;服务器检查它们是否有效 5.)服务器将它们发回 6.)客户端发送3个32位数字:pid,uid和gid 7.)服务器发送回自己版本的这些号码。

我不明白这次握手的目的是什么,因为从安全的角度来看,它完全没有价值。

答案 1 :(得分:3)

似乎divB和Mark的答案都是正确的,但它们都遗漏了一些细节,所以希望这更加完整。

这里有两种不同的实现方式。我没有对谁实现哪个实现进行详尽的调查,但在撰写本文时,当前版本的cygwin使用divB描述的实现,MsysGit使用Mark描述的实现。

初始化服务器:

  1. 创建套接字(AddressFamily = IPv4,Type = Stream,Protocol = TCP)。 (.NET / MFC
  2. 将其绑定到环回(127.0.0.1)。 (.NET / MFC
  3. 告诉套接字听。 (.NET / MFC
  4. 生成随机的16字节GUID。
  5. 根据TCP端口和GUID创建包含以下内容的文件。使用原始示例,59108是TCP端口,282F93E1-9E2D051A-46B57EFC-64A1852F是GUID。

    在cygwin实现中,套接字文件内容为:

    !<socket >59108 s 282F93E1-9E2D051A-46B57EFC-64A1852F
    

    在msysgit实现中,套接字文件的内容是:

    !<socket >59108 282F93E1-9E2D051A-46B57EFC-64A1852F
    

    区别在于额外的&#34; s&#34;在端口和GUID之间。

  6. 在此文件上设置系统属性。

  7. 仅在msysgit实现中,创建名为cygwin.local_socket.secret.58598.282F93E1-9E2D051A-46B57EFC-64A1852F的命名等待句柄(InitalState = False,Reset = AutoReset)。 (.NET / MFC

    58598是通过在端口上使用HostToNetworkOrder函数(作为16位无符号整数)得到的。即59108 == 0xE6E4和58598 == 0xE4E6。

  8. 处理连接:

    1. 接受传入套接字。 (.NET / MFC)。
    2. 仅在cygwin实现的情况下,握手包括:
      1. 读取16个字节。如果这些与GUID不匹配,则失败。
      2. 发送相同的16个字节。
      3. 读取12个字节作为3个32位整数。他们是调用过程中的pid,uid和gid。
      4. 返回12个字节(3个32位整数)。使用服务器的pid和收到的uid和gid。
    3. 仅在msysgit实现的情况下,通过以下方式与客户端同步:
      1. 获取传入套接字的端口。对于此示例,我们将其称为63524
      2. 打开客户端的现有等待句柄。 (.NET / MFC)。您需要将端口转换为网络字节顺序,就像我们对服务器所做的那样。因此,对于此示例,名称为cygwin.local_socket.secret.9464.282F93E1-9E2D051A-46B57EFC-64A1852F
      3. 发信号通知服务器并等待客户端(ToSignal = server,WaitOn = client,Timeout = 10000毫秒,ExitContext / Alertable = False)。 (.NET / MFC)。不是100%肯定ExitContext / Alertable参数,但False似乎有效。
    4. 将套接字移交给(希望已存在)代码,无论您正在做什么(在我们三个人的情况下,似乎都是ssh代理)。

答案 2 :(得分:2)

我已经找到了一些能够正确运行Git附带的OpenSSH(ssh-agent.exe)的东西:

服务器端的安装包括以下步骤:  1.创建一个&#34;秘密字符串&#34;它由四组八个十六进制数字组成,用短划线分隔(&#34; - &#34;)  2.听一个当地的港口  3.使用名为cygwin.local_socket.secret的模式EventWaitHandle创建EventResetMode.AutoReset。[secret string]。[此处监听端口号,字节顺序颠倒]  4.写出&#34; socket&#34;文件,由字符串组成![此处为端口号,字节顺序未反转] [秘密字符串]

当连接进入时,必须执行以下步骤:  1.使用事件名称cygwin.local_socket.secret打开客户端的EventWaitHandle.OpenExisting()事件句柄。[远程端口号,字节顺序颠倒]。[secret string]  2.发信号通知服务器的事件句柄,并等待客户端的等待句柄用`EventWaitHandle.SignalAndWait()

发出信号。

我同意看起来邮件列表中讨论的补丁从未应用过。我编写的序列似乎更接近该列表中讨论的序列,并且它与我从Cygwin挖出的代码相匹配。

我不理解我发现的工作与divB发现工作之间的差异,但我确认它与我使用的软件(Git的OpenSSH)一起运行