我的 CGI 应用程序正在尝试使用 SSPI Schannel 创建与另一台服务器的 TLS 连接。 http://www.coastrd.com/c-schannel-smtp
握手过程首先检查“我的”证书存储中的证书 http://msdn.microsoft.com/en-us/library/aa376560(VS.85).aspx
这个函数返回零,GetLastError 也返回零!?我认为这是一个权限问题。例如,如何在不将 IUSR 提升为管理员的情况下使其正常工作?
添加
访问用户证书需要以特定用户身份运行,访问用户私钥需要用户已使用密码在本地登录,或者服务器已启用委派。
每个人都可以读取机器证书,但访问私钥需要管理员权限(或本地用户),除非您调整 ACL。
添加
在这种情况下,证书没有限制,但是“我的”证书存储是空的,我不想为此购买证书。
我目前正在使用 WS2003。我连接的服务器是 gmail.com 使用 TLS 发送电子邮件。我的代码可以查找证书,但我没有。在我所做的阅读中,获得证书似乎是一个巨大的头痛,注册和购买和安装,否则你只是得到一个没有帮助的临时解决方案。除非您知道获取证书的简单方法,否则这比我想从 CGI 应用程序发送电子邮件要麻烦得多。还有其他方法吗?
我非常感谢您的帮助 Joe,但 30 美元/年 x nServers 不是一个选择。我想知道是否有办法将任务交给以管理员权限运行的另一个进程,比如服务?我什至可以创建一个应用程序,它计划从给定文件夹中读取并发送在那里找到的任何电子邮件。除此之外,我将不得不尝试将 CGI 应用程序提升为管理员。
添加
Goyuix,谢谢你的建议。挑战在于提供一个独立的解决方案,而无需求助于其他库,如 .NET (60MB) 或 ASP 以及随之而来的问题。
你是对的,我只需要服务器身份验证。我不知道只能对一侧进行身份验证。您的声明:“没有客户端证书不应阻止您为 SMTP 建立安全通道。您可能只需要围绕握手的那一部分进行编码。” 原来是解决方案。
这让我想起了以前的水管工笑话。管道工被要求疏通排水管。他看了一眼,掏出一把锤子,在管子上敲了一下。他要求为 5 分钟的工作支付 180 美元,其中包括 30 美元的标注费用和 150 美元的费用,以了解在哪里打管道。
谢谢你们俩。这是一个漫长的上坡路。
我看到的最佳选择是使用机器证书并授予 IUSR 帐户读取证书私钥的权限。这是一个手动步骤,但非常简单,只需要完成一次。
您的情况是否还有其他要求会阻止更改证书权限?
入门指南
首先,你需要一个证书。您可以生成自己的,但取决于您希望如何使用它以及验证它的另一端,您可能需要购买一个。我不会介绍如何生成证书。如果您以前从未使用过证书和证书颁发机构,我建议您先了解它们。
除非您另有评论,否则我假设您使用的是 Windows Server 2003。
1)将证书安装到机器存储中。转到开始 | 运行并进入 MMC 得到一个空白的 MMC 控制台。转到文件 | 添加/删除管理单元。单击添加按钮以选择管理单元。从列表中选择证书并单击添加。选择计算机帐户选项,然后选择下一步、完成、关闭,最后确定。
2) 将证书导入Machine Store。展开树并选择个人文件夹。右键单击个人并选择所有任务,导入。按照向导完成该过程。证书现在应该在机器存储中。
3)调整私钥权限。在 Windows 2008 上,它被添加到证书管理器 GUI。在 Windows 2003 中,您需要下载Windows Server 2003 Resource Kit Tools。使用以下命令的格式来设置权限:
其中 'LOCAL_MACHINE\My' 是本地计算机中的个人证书存储,'mycert' 是您的证书的名称,而 USER_ACCOUNT 是将获得私钥读取权限的帐户。您可以尝试使用 IUSR 帐户,但您可能需要使用“网络服务”,具体取决于您的 CGI 应用程序运行的确切上下文。您需要重新启动 IIS 才能使更改生效。WinHttpCertCfg的文档涵盖了它在做什么。
您现在应该有权访问私钥。您仍将使用带有 MY 标志的 CertOpenSystemStore。
希望有帮助。
编辑2:
GoDaddy 是一个容易获得具有公认权威的证书的地方。您可以花 30 美元获得有效期为 1 年的 SSL 证书。如果您四处打猎,其他地方可能会更便宜。做起来并不难。大多数网站都非常用户友好,可以轻松购买证书。
由于您正在进行相互身份验证,因此您需要一个具有有效权限的证书,而不仅仅是您可以自己创建的自签名证书,因为 Gmail 服务器无法验证它。
schannel 代码试图破解“MY”存储的唯一原因是寻找可用于客户端身份验证的潜在证书,作为初始握手的一部分。在您的示例中,我想您真的只关心服务器身份验证(例如,确保您的客户端正在与它认为的服务器通信)。没有客户端证书不应阻止您为 SMTP 建立安全通道。您可能只需要围绕握手的那一部分进行编码。
如果您还需要客户端身份验证,那么您可能必须:
至于修复链接代码......好吧 - 如果可以的话,我建议尝试使用 .NET 框架附带的 SmtpClient 代码。它支持加密通信,理论上应该“正常工作”。托管 C++ 甚至是一种选择吗?或者更好的是,只需为此编写一个 ASP.NET 处理程序?
http://msdn.microsoft.com/en-us/library/system.net.mail.smtpclient_members.aspx
您可能还想尝试在StackOverflow.com上询问一些相关的代码问题,那里的人也可以提供帮助。