How to get next certificate in chain - c

I want to get parent certificate (or all certificates in chain for that matter) from Windows Certificate Store (assuming I know the location of the end certificate). I need to get each one in order to build my own custom X509_STORE (using OpenSSL).
I think the proper course of action would be:
obtain first certificate using CertFindCertificateInStore (done)
get the certificate chain using CertGetCertificateChain (done)
extract the certificates from chain (?)
for each certificate in chain, convert it using d2i_X509 (done)
or
obtain first certificate using CertFindCertificateInStore (done)
get the parent certificate (if exists) (?)
convert it using d2i_X509, go to 2. (done)
Then create the store.
The question to answer is then - how to get the parent certificate or all certificates in chain using Windows Certificate Store? I'm probably missing some more or less occult function here.

as the CertFindCertificateInStore outputs a chain context, one can access it's members using the beautiful construction:
chainContext->rgpChain[0]->rgpElement[iCertIndex]->pCertContext->pbCertEncoded
where iCertIndex is between 0 (end-certificate) and chainSize -1 (self-signed root certificate).

Related

Using LDAP template to find certificate

Our organization stores signing certificates in Active Directory. We are using anonymous bind to search for them at a base DN (e.g. OU=MY ORG,dc=mydc,dc=org). I have been trying to use the Spring LdapTemplate to look them up, but no matter what method I use, I get the cryptic InterruptedNamingException.
Assuming a cert subject of cn=mycert.myorg.com
My code looks like this
LdapContextSource contextSource = new LdapContextSource();
contextSource.setUrl(String.format(LDAP_URL_FORMAT, ldapCertStoreParameters.getServerName(),
ldapCertStoreParameters.getPort()));
contextSource.setBase(ldapCertStoreParameters.getBaseDn());
contextSource.setAnonymousReadOnly(true);
contextSource.afterPropertiesSet();
LdapTemplate ldapTemplate = new LdapTemplate(contextSource);
ldapTemplate.setIgnorePartialResultException(true);
ldapTemplate.afterPropertiesSet();
X500Principal principal = x509CertSelector.getSubject();
Object obj = ldapTemplate.lookup(new LdapName(principal.getName()));
The X500 principal's name is the whole dn. cn=mycert.myorg.com,OU=MY ORG,dc=mydc,dc=org
I have also tried the search using just the cn.
We have verified that the DN exists on the server using Apache Directory Studio.
• I would suggest you to please remove the call altogether or set the ‘userSearchBase’ either to an empty String (“”) as per the given example in the below community thread: -
Configure Spring security for Ldap connection
As in the ‘AbstractContextSource’, set the base suffix from which all operations should origin. If a base suffix is set, you will not have to (and, indeed, must not) specify the full distinguished names in any operations performed. Since you specified the full DN for the userDN/filter, you must not specify the base.
AD servers are apparently unable to handle referrals automatically, which causes a ‘PartialResultException’ to be thrown whenever a referral is encountered in a search. To avoid this, set the ‘ignorePartialResultException’ property to true. There is currently no way of manually handling these referrals in the form of ‘ReferralException’, i.e., either you get the exception (and your results are lost) or all referrals are ignored (if the server is unable to handle them properly). Neither is there any simple way to get notified that a ‘PartialResultException’ has been ignored.
For more details regarding the LDAP template search for Active Directory stored certificates, kindly refer to the link below: -
https://docs.spring.io/spring-ldap/docs/current/apidocs/org/springframework/ldap/core/LdapTemplate.html
• Also, please try to refer to the below documentation for configuration of Springboot LDAP template configuration through certificates stored in Active Directory: -
https://www.baeldung.com/x-509-authentication-in-spring-security

Where to store a Authorization Bearer Token in Salesforce?

We have an external vendor that requires us to include a bearer token in the http request header when we communicate with the API. This token shouldn't be left in the code unencrypted so where is the best place to store it? The Named Credential type doesn't seem to support storing a simple token and the Custom Setting option seems overly complicated and unnecessary. This is a single token string that will be used for every API call regardless of which user. I have searched high and low on google and haven't found an obvious solution that works.
There are some options but they're limited for your code as end user. A determined developer/sysadmin will learn the value eventually.
If you'd build a managed package you could use a protected custom setting (managed package's code could see it but not the client code, even sysadmins)
Check some of these:
https://developer.salesforce.com/page/Secure_Coding_Storing_Secrets
https://salesforce.stackexchange.com/questions/226110/what-is-the-best-way-of-storing-username-and-password-in-salesforce
https://salesforce.stackexchange.com/questions/478/using-transient-keyword-to-store-password-in-hierarchy-custom-setting
https://salesforce.stackexchange.com/questions/55008/is-encrypting-passwords-in-protected-custom-settings-a-security-requirement
You could make a custom setting with 2 text fields, 1 with encryption key and 1 with encrypted value in it. Look at Crypto class.
Blob exampleIv = Blob.valueOf('Example of IV123');
Blob key = Crypto.generateAesKey(128);
Blob data = Blob.valueOf('Data to be encrypted');
Blob encrypted = Crypto.encrypt('AES128', key, exampleIv, data);
Blob decrypted = Crypto.decrypt('AES128', key, exampleIv, encrypted);
String decryptedString = decrypted.toString();
System.assertEquals('Data to be encrypted', decryptedString);
Your initialisation vector could be org's id or something else that's easy to access and unlikely to change (I don't know if your vendor's API has test and prod endpoints but it's an added bonus that after sandbox refresh this will fail to decrypt OK until you change the custom setting... you wouldn't want to send test messages to production API), you'd generate key once & store it in setting.

SSL_CTX_set_verify() callback and depth of root CA

I'm writing my own callback function in C for SSL_CTX_set_verify() to perform additional certificate checks (when the preverify_ok parameter is 1). However, I want to perform the checks only for the root CA certificate.
Within the callback, the function X509_STORE_CTX_get_error_depth() gets the current depth where a depth of 0 is the leaf certificate. But how can I find out what the depth of the root CA certificate is? I.e. the depth of the first time my callback is called so I can compare it against the current depth.
Yes, there is the SSL_CTX_get_verify_depth() function, but that returns the depth limit (if any), so that's not what I want.
In the case of the root CA, the current cert and issuer cert in the Store Context will be same. So, a check like below in your code should do the trick:
if(X509_STORE_CTX_get0_current_issuer(ctx) == X509_STORE_CTX_get_current_cert(ctx))
{
//Do the special root certificate related checks.
}

xmlsec library - obtain subject of signing key

I am using the xmlsec library to verify the signature of an SAML assertion. My code is almost identical to the verify4.c example provided on the xmlsec web page.
I am linking against the xmlsec-openssl lib, so using openssl as the crypto engine.
I was expecting that xmlsec would consider the signature valid only if it was signed with one of the specific certificate(s) I had loaded into the key manager.
However, the signature seems to be considered valid if signed with ANY certificate that can be verified by openssl. This means that someone could forge an SAML response just by buying a certificate from a trusted root CA and using that to sign whatever response they want.
Not only that, but the xmlsec1 command line tool provided with the library seems to do the same thing:
xmlsec1 --verify --dtd-file saml.dtd --pubkey-cert-pem my_cert.cer sample_saml_assertion.xml
...
OK
SignedInfo References (ok/all): 1/1
Manifests References (ok/all): 0/0
Actually, in an ideal world, I would be happy for any valid signing key to be used as long as I could identify the subject of the key and therefore confirm it was signed by the entity I expected. That would simplify matters when the sender of the SAML responses changed their signing key. But I have not been able to find a simple way to extract the details of the cert that was used to verify the signature.
Failing that, can I make it accept only the certificate(s) I have specified when verifying the signature?
While writing the question I realized I had not tried the --print-debug option for xmlsec1. When I tried that I found that it does indeed print the subject and issuer of the cert that was used to verify the signature.
That led me to realize that the information must be present, so it is a question of how to access it. Tracing through the code, I was able to write this little snippet which does the trick:
/* If signature is valid, then the list dsigCtx->signKey contains
the signing key, data dsigCtx->signKey->dataList contains the certificate */
xmlSecPtrListPtr keyDataList = dsigCtx->signKey->dataList;
/* Iterate through the data list to find the X509 cert */
xmlSecSize n = xmlSecPtrListGetSize(keyDataList);
xmlSecSize i;
for (i=0; i<n; i++) {
xmlSecKeyDataPtr item = xmlSecPtrListGetItem(keyDataList, i);
if (xmlSecKeyDataIsValid(item) && xmlSecKeyDataCheckId(item, xmlSecOpenSSLKeyDataX509Id)) {
/* Extract openssl cert */
X509* cert = xmlSecOpenSSLKeyDataX509GetKeyCert(item);
char cn_buff[256];
if(cert != NULL) {
/* Get the CN */
X509_NAME * subject_name = X509_get_subject_name(cert);
int nid_cn = OBJ_txt2nid("CN");
X509_NAME_get_text_by_NID(subject_name, nid_cn, cn_buff, 255);
/* Here you would compare it to the expected certificate */
fprintf(stdout, "CN=%s\n", cn_buff);
} else {
fprintf(stdout, "Failed to obtain signing key cert\n");
}
}
}
This seems a very complex way to obtain something so fundamental, so I am sure there must be an easier way.

SignedXml.CheckSignature() is true, but SignedXml.CheckSignature(certificate) is false

I'm generating a SAML2 token from ADFS, signed by certificate. Now I'm trying to verify that signature, using the same certificate.
X509Certificate2 cert = LoadCert();
XmlDocument token = LoadXmlToken(); //SAML2 token
XmlElement signature = GetSignatureElement(token);
SignedXml signedXml = new SignedXml(token);
signedXml.LoadXml(signature);
bool result1 = signedXml.CheckSignature(); //true
bool result2 = signedXml.CheckSignature(cert, false); //false
CheckSignature() verifies signature against the public key contained in the token.
CheckSignature(cert, [true/false]) verifies signature against the private key from the certificate.
How can it be that one works and the other doesn't?
The method signedXml.CheckSignature() evaluates the xml signature integrity against the certificate contained inside the own signature.
The method SignedXml.CheckSignature(X509Certificate2, Boolean) evaluates the xml signature integrity against the certificate passed as first parameter, and optionally if the second parameter is false it checks also the validity of the certificate in the first parameter.
Probably the second method returns false because you are specifying a wrong certificate: is not the certificate which performs the signature or its state is revoked or expired or it is issued by an untrusted certificate authority.
We had to enable IP address and/or URL's on our outbound firewall for the checksignature method when using the certificate check. In our case it tried to communicate with the root CA and the sub CA's website. With the firewall closed the method failed, but once we identified the URL's being accessed and opened up the firewall it started to work as expected.
The difference is in the second parameter (boolean). If you look at documentation of parameterless CheckSignature method you can find this:
This method also computes the digest of the references and the value of the signature.
The second method has this documentation. If the second parameter is set to
false then verify both the signature and certificate.
To verify certificate this method will probably build whole certificate chain and check revocation information of all certificates in this chain.

Resources