I have been struggling to get a secure RPC client/server using Microsoft RPC. I am not using COM, just straight C.
I have created a Root CA certificate and created a certificate signed by this cert for the server. The certs are installed into cert stores.
RPC works fine unencrypted and it will even work with SCHANNEL setup, just not encrypted.
ServerCode:
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
Client Code:
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)
Given all of this RPC will work, but it will not be encrypted as verified with wireshark. I have worked this with a very minimal SCHANNEL structure definition and not using qos structure. Nothing makes much difference. the only thing that really makes a difference is if I change RPC_IF_ALLOW_CALLBACKS_WITH_NO_AUTH to RPC_IF_ALLOW_SECURE_ONLY. Then I get an access denied when making an RPC call. From what I understand this is the normal functionality of SCHANNEL and you must provide your own authentication within the Security Callback.
When I call RpcBindingInqAuthClient in my security callback I recieve the error 1746: The binding does not contain any authenticatioin information.
I have looked through MSDN, a the few various links scattered on the web, but there is little to know help on getting SCHANNEL working.
My choice for SCHANNEL is I can't rely on kerberos or ntlm. I am running tcp over the internet so certificates are what work for me. I can't use http because I can't setup IIS on my server, DCE seems to be even less documented than schannel.
Thanks!