我一直在努力使用 Microsoft RPC 获得安全的 RPC 客户端/服务器。我没有使用COM,只是直接使用C。
我已经创建了一个根 CA 证书,并为服务器创建了一个由该证书签名的证书。证书安装到证书存储中。
RPC 可以在未加密的情况下正常工作,它甚至可以与 SCHANNEL 设置一起使用,只是未加密。
服务器代码:
RpcServerUseProtseqEpW(
L"ncacn_ip_tcp",
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
port,
NULL);
CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
(HCRYPTPROV)NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
L"MY")
CertFindCertificateInStore(
hStore,
X509_ASN_ENCODING|PKCS_7_ASAN_ENCODING,
CERT_FIND_SUBJEECT_STR,
subject,
NULL);
RpcCertGeneratePrincipalNameW(
ccert_ctx_server,
RPC_C_FULL_CERT_CHAIN,
serverPrincName);
schannel.dwVersion = SCHANNEL_CRED_VERSION;
schannel.cCreds = 1;
schannel.paCred = &ccert_ctx_server;
RpcServerRegisterAuthInfoW(
serverPrincName,
RPC_C_AUTHN_GSS_SCHANNEL,
NULL,
&schannel);
RpcServerRegisterIf2(
h_v1_ifspec,
NULL,
NULL,
RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH // seems to be required by SCHANNEL
RPC_C_LISTEN_MAX_CALLS_DEFAULT,
(unsigned)-1,
SecurityCallback); SecurityCallback returns RPC_S_OK
客户代码:
RpcStringBindingComposeW(
NULL,
L"ncacn_ip_tcp",
address,
port,
NULL,
&stringBinding);
RpcBindingFronStringBindingW(
stringBinding,
hBind);
CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
(HCRYPTPROV)NULL,
CERT_SYSTEM_STORE_LOCAL_MACHINE | CERT_STORE_READONLY_FLAG,
L"MY")
CertFindCertificateInStore(
hStore,
X509_ASN_ENCODING|PKCS_7_ASAN_ENCODING,
CERT_FIND_SUBJEECT_STR,
subject,
NULL);
RpcCertGeneratePrincipalNameW(
ccert_ctx_server,
RPC_C_FULL_CERT_CHAIN,
serverPrincName);
schannel.dwVersion = SCHANNEL_CRED_VERSION;
schannel.cCreds = 1;
schannel.paCred = &ccert_ctx_client;
RpcServerRegisterAuthInfoW(
serverPrincName,
RPC_C_AUTHN_GSS_SCHANNEL,
NULL,
&schannel);
RpcBindingSetAuthInfo(
hBind,
serverPrincName,
RPC_C_AUTHN_LEVEL_PKT_INTEGRITY,
RPC_C_AUTHN_GSS_SCHANNEL,
&schannelCred,
RPC_C_AUTHZ_NONE)
鉴于所有这些 RPC 都可以工作,但它不会像使用wireshark 验证的那样被加密。我用一个非常小的 SCHANNEL 结构定义而不是使用 qos 结构来解决这个问题。没什么大不了的。唯一真正有所作为的是如果我将 RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH 更改为 RPC_IF_ALLOW_SECURE_ONLY。然后我在进行 RPC 调用时被拒绝访问。据我了解,这是 SCHANNEL 的正常功能,您必须在安全回调中提供自己的身份验证。
当我在安全回调中调用 RpcBindingInqAuthClient 时,我收到错误 1746:绑定不包含任何身份验证信息。
我浏览了 MSDN,一个分散在网络上的几个不同的链接,但是对于 SCHANNEL 的工作几乎没有什么帮助。
我对 SCHANNEL 的选择是我不能依赖 kerberos 或 ntlm。我在互联网上运行 tcp,所以证书对我有用。我不能使用 http,因为我不能在我的服务器上设置 IIS,DCE 的文档似乎比 schannel 还要少。
谢谢!