Microsoft RPC SChannel not encrypted - c

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!

Related

How to obtain the key agreement algorithm used in TLS 1.3 handshake using OpenSSL API?

I was modifying the example client code given on the OpenSSL s_client page to understand a few functions. I added the following lines after the chain verification part :
const SSL_CIPHER* curr_cipher = SSL_get_current_cipher(ssl);
printf("SSL_CIPHER_standard_name: %s\n", SSL_CIPHER_standard_name(curr_cipher));
printf("SSL_get_cipher_version: %s\n", SSL_get_cipher_version(ssl));
int kx_nid = SSL_CIPHER_get_kx_nid(curr_cipher);
printf("SSL_CIPHER_get_kx_nid: %d\n", kx_nid);
printf("OBJ_nid2ln(%d): %s\n", kx_nid, OBJ_nid2ln(kx_nid));
printf("SSL_CIPHER_description: %s\n", SSL_CIPHER_description(curr_cipher, NULL, 0));
Instead of getting the key exchange algorithm used, I got the following output after connecting to random.org using TLS 1.3 :
SSL_CIPHER_standard_name: TLS_AES_256_GCM_SHA384
SSL_get_cipher_version: TLSv1.3
SSL_CIPHER_get_kx_nid: 1063
OBJ_nid2ln(1063): kx-any
SSL_CIPHER_description: TLS_AES_256_GCM_SHA384 TLSv1.3 Kx=any Au=any Enc=AESGCM(256) Mac=AEAD
The man page for SSL_CIPHER_get_kx_nid says it returns NID_kx_any for TLS 1.3. How can I programatically get the actual key agreement (NID_kx_ecdhe) and authentication protocol (NID_auth_rsa) used in the handshake from the SSL object?

SAML error "SignatureStatus: NOT_PRESENT"

UPDATE
I found that if I add a trusted cert to SPOptions.ServiceCertificates and set SPOptions.AuthenticateRequestSigningBehavior = Sustainsys.Saml2.Configuration.SigningBehavior.IfIdpWantAuthnRequestsSigned; and set IdentityProvider.WantAuthnRequestsSigned = true, the signature element is included.
Original Question:
Having troubles connecting to an IDP with the following AuthnRequest:
<saml2p:AuthnRequest xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion" ID="idf299bf8aa08542d193e022cb047e5ecc" Version="2.0" IssueInstant="2019-07-23T00:10:13Z" Destination="https://example-idp.com" AssertionConsumerServiceURL="https://example-sp.com/Acs">
<saml2:Issuer>https://example-sp.com</saml2:Issuer>
</saml2p:AuthnRequest>
The IDP says: "SignatureStatus: NOT_PRESENT". I'm guessing that means that the authnrequest should have a <ds:Signature section? If so, how do I configure Sustainsys.Saml2.AspNetCore2 to include it?
The metadata xml I received from the idp contains a <ds:Signature section, but looking at the source code for Sustainsys.Saml2.AspNetCore2, it looks like that part of the metadata gets ignored when deserializing?
I'm not very familiar with the internals of SAML, so sorry if this is a silly question.
You'll want to generate a self-signed .pfx file that contains both your public cert and private key. We use azure key vault, but you could also use openssl. Lots of resources that explain how to generate one of those and load it into a c# X509Certificate2 instance.
Once you have an instance of X509Certificate2, set options.SPOptions.AuthenticateRequestSigningBehavior = Sustainsys.Saml2.Configuration.SigningBehavior.IfIdpWantAuthnRequestsSigned;
And set IdentityProvider.WantAuthnRequestsSigned = true.
And then add the X509Certificate2 instance like so: options.SPOptions.ServiceCertificates.Add(myX509Certificate2);
Then run your app and start the SAML SSO process. You can use hookbin or the like to see what it sends in the AuthnRequest for SAMLRequest. You can extract the xml from that by url decoding it and then base64 decoding it like so in javascript, for instance to confirm signature xml is set and correct: atob(decodeURIComponent(samlRequestValue))

Windows RPC access denied even with RPC_C_AUTHN_NONE

I have this error while trying to connect my RPC client to my RPC server:
Error occurred:5
Some googling showed me the meaning of this error: access denied.
The trouble does not come from the firewall.
Here is the server part, where I specify RPC_C_AUTHN_NONE to let everyone connect:
RPC_STATUS status;
printf("RPC Server Starting...\n");
status = RpcServerUseProtseqEp(
(unsigned char *)"ncacn_ip_tcp",
RPC_C_PROTSEQ_MAX_REQS_DEFAULT,
(unsigned char *)"9191",
RPC_C_AUTHN_NONE);
if (status) { printf("Error:%d\n", status); exit(status); }
printf("RPC Server Configured\n");
Here is the client part raising the error:
RpcTryExcept {
unsigned char szMsg[] = "Client: I can RPC now!\n";
md5(szMsg);
} RpcExcept(1) {
printf("Error occurred:%d\n", RpcExceptionCode());
}
RpcEndExcept
How do I correct this issue, in order to let any RPC client connects?
And in the same order, do you know a good RPC documentation for Windows RPC authentication?
Many thanks!
I have spent some time figuring why this happened, and I provide this answer as I found a solution, in order to help those who might encounter this trouble:
By default, RPC connection are only granted to authenticated clients. This can be changed by editing a registry entry or applying a GPO to disable restrictions for unauthenticated users as specified here.

SSL Cipher help in C

I am trying to Use SSL on top of tcp/ip to send an HTTPS request to a site using C. I have no access to curl or other standard libraries. Pretend like i can't load any libraries at all.
I need to set an SSL Profile Cipher. When I successfully use curl on my linux box to talk with the server I see: SSL Connection using ECDHE-RSA-AES128-SHA
If my options for setting the cipher are:
SSL_kRSA (RSA Key Exchange)
SSL_kEDH (tmp DH key no DH cert)
SSL_aRSA (Authenticate with RSA)
SSL-aDSS (Authenticate with DSS)
SSL_DES (DES)
SSL_3DES (3DES)
SSL_RC4 (RC4)
SSL_RC2 (RC2)
SSL_AES (AES)
SSL_MD5 (MD5)
SSL_SHA1 (SHA1)
SSL_SHA256 (SHA256)
SSL_SHA384 (SHA384)
SSL_RSA ([SSL_kRSA|SSL_aRSA] RSA)
SSL_DSS ([SSL_aDSS] Authenticate with DSS)
I can set multiple things by something like:
SSL_RSA | SSL_AES
Protocol is TLSv1.2
What should my cipher look like?
"Pretend like i can't load any libraries at all." If that is true, you will need to implement the cipher itself plus the SSL handling layer ^_^.
Assuming you are using OpenSSL and have TCP established with socket_fd, you need to create a SSL_CTX with SSL_CTX_new (SSLv23_client_method()). Normally, to set the cipher list, you use SSL_CTX_set_cipher_list(ctx, "HIGH:!aNULL:!eNULL:#STRENGTH"), see http://openssl.org/docs/apps/ciphers.html for all available options, you may specific a particular cipher.
Then create a SSL session with SSL_new(ctx) and SSL_set_fd (ssl, socket_fd), after that use SSL_connect(...), SSL_read(...)/SSL_write(...) to communicate with server.
After all have been done, SSL_shutdown(...) and SSL_Free(...), SSL_CTX_Free(...).

Authentication fails in databasedotcom

I am trying to adopt databasedotcom gem, but couldn't get beyond the authentication. Here is what I did (after installing databasedotcom gem):
rails c (or irb then require 'databasedotcom')
client=Databasedotcom::Client.new :client_id => 'foo', :client_secret=>'bar'
client.ca_file = '/Users/tjiang/missioncontrol/tmp/ca-bundle.crt'
client.verify_mode = OpenSSL::SSL::VERIFY_PEER
client.authenticate :username=>'myusername', :password=>'mypassword'
All credentials are copy-and-pasted in the process so no mistake there; the certificate was downloaded here: http://certifie.com/ca-bundle/ca-bundle.crt.txt
I tried Ruby 187 and 193 as well as inside and outside Rails, repeatedly, but always got this error message:
Databasedotcom::SalesForceError: authentication failure from /Library/Ruby/Gems/1.8/gems/databasedotcom-1.3.0/lib/databasedotcom/client.rb:112:in `authenticate'
I wonder what I have missed here? Particularly, I am concerned about the Callback URL I used when creating a Remote Access in Salesforce (I tried 'oob', 'http://localhost:3000', and 'https://www.salesforce.com', but none made any difference).
It turns out this is due to a bug in databasedotcom. When you use username and password to authenticate, it puts them into an url query string WITHOUT encoding and POST a request with that url. As a result, the plus sign in my username will be interpreted as a blank space.
Solution: CGI::escape() both your username and password.

Resources