Create Certificates for PKINIT-based Kerberos login on Active Directory - active-directory

I'm trying to set-up a PKINIT-based Kerberos login on a Active Directory. The login shall be performed using sssd on Linux. However, the kerberos server does not accept the client certificate. We receive an error with event ID 21: Certificate for user REALM/Domainuser is not valid on the server and sssd says: Client name mismatch.
The certificates were created with the following procedure on a different Linux machine:
openssl req -new -key keyfile.pem -out reqfile.pem -subj
"/CN=Domainuser/O=AAA/C=DE/OU=BBB"
env REALM=REALM.local CLIENT=Domainuser openssl x509 \
-CAkey ../ca_privkey.pem -CA ../ca_cert.pem -req -in reqfile.pem \
-extensions client_cert -extfile extensions.client \
-days 365 -out certfile.pem
We installed the AD CA on the Windows Server that hosts the AD itself. We exported the certificte of this CA to the Linux machine and stored its private key and certificate in the ca_privkey.pem and ca_cert.pemfiles to use it with openssl.
The client_cert we used during signature creation was created using the template suggested by sssd. The only thing we added is the crlDistributionPoints option to include the CRL of the CA:
[client_cert]
basicConstraints=CA:FALSE
keyUsage=digitalSignature,keyEncipherment,keyAgreement
extendedKeyUsage=1.3.6.1.5.2.3.4
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer
issuerAltName=issuer:copy
subjectAltName=otherName:1.3.6.1.5.2.2;SEQUENCE:princ_name
crlDistributionPoints=URI:http://link-to-CRL-of-CA
[princ_name]
realm=EXP:0,GeneralString:${ENV::REALM}
principal_name=EXP:1,SEQUENCE:principal_seq
[principal_seq]
name_type=EXP:0,INTEGER:1
name_string=EXP:1,SEQUENCE:principals
[principals]
princ1=GeneralString:${ENV::CLIENT}
The realm used for the authentication is REALM.local (equal to the AD Domain). The environment variables REALM and CLIENT are set to REALM.LOCAL and pkuser during certificate creation and the user pkuser also exists in the AD (Password-based login is possible).
I have no clue why the authentication is not successful. Do you have any ideas what might be wrong in the configuration or give me a hint s.t. Windows prints a more detailed error message? Note, that certutil -verify -urlfetch certfile.pem is able to validate the whole certificate chain and does not print any errors when executed with the Administrator command on the AD server.
I assume that there are some configuration errors on the Windows Server. This is the first time I configured a Windows Server ;)

Finally, we figured out what the problem was. Windows AD requires additional extended key usage fields to allow the authentication.
You have to add 1.3.6.1.5.5.7.3.2 and 1.3.6.1.4.1.311.20.2.2.
Further, the SAN must be set to: otherName:1.3.6.1.4.1.311.20.2.3;UTF8:<client-name>#<realm>

Related

Linked Server Certificate issue

I have 2 SQL Servers(2017): A and B.
Server_A does not have a certificate and encryption is not enabled.
Server_B has a certificate and encryption is enabled.
While logged onto Server_A:
SELECT * FROM [Server_B].MyDB.dbo.MyTable -- This works
While logged onto Server_B:
SELECT * FROM [Server_A].SomeDb.dbo.AnyTable -- This fails with the error:
"OLE DB provider "SQLNCLI11" for linked server "Server_A" returned message "Client unable to establish connection".
Msg -2146893019, Level 16, State 1, Line 11
SSL Provider: The certificate chain was issued by an authority that is not trusted."
This seems backwards to me. I would think that the first query would fail because it originates from a SQL Server with no certificate. Instead the SQL Server with a certificate fails when communicating to a "no certificate" server.
I would like to understand why this is failing in this way.
Also, what do I have to do to make the 2nd query succeed? I suspect installing a certificate on Server_A will solve this. Does this sound correct?
Install a certificate on server A does not solve the problem.
If you don't have the certificate you can get the databases list with the relative certificate with the below query see this post
use master;
go
select
database_name = d.name,
dek.encryptor_type,
cert_name = c.name
from sys.dm_database_encryption_keys dek
left join sys.certificates c
on dek.encryptor_thumbprint = c.thumbprint
inner join sys.databases d
on dek.database_id = d.database_id;
Once you have obtained the certificate name you can BACKUP it to a folder.
From here you must know a little bit about certificates.
Each certificate has an "Issuer" (someone who signs the certificate) and/or a chain (intermediate path signed by an ancestor intermediate, and so on) when you query the db, your PC read the certificate and verify the chain.
The error says:
The certificate chain was issued by an authority that is not trusted."
This means: "I don't trust the certificate because it is emitted by someone whom I don't trust"
An exception is for a self-signed certificate where the issuer of the certificate is itself and it has no chain (single node).
You must open the certificate and see the chain.
On windows:
If is self-signed, install the certificate on "Trusted root certificate authority"
If is NOT self-signed you must lookup for the chain certificate and install it on "Trusted root certificate authority"
On Linux, I don't remember exactly and you must look on google about it.
Max,
Thank you for the reply. Your answer regarded certificates at the database level. Indeed when I query the sys.certificates system catalog it returns the certificates used for TDE encryption. However, the certificates I am using are for Transport Layer Security (TLS) encryption which are at the server level.
But your answer highlighted the error "The certificate chain was issued by an authority that is not trusted" and this got me thinking along different lines. AND you mentioned I needed to 'open' the certificate. When I opened the cert that I had exported it stated it could not be verified. Turns out I exported it incorrectly. My 2nd export attempt worked.
As I re-read the MS Docs I also realized I missed the step of granting the SQL Server service account read permission. Once I did that the Linked Server successfully connected.
So in summary if your client is another SQL Server you need to export the cert from the target server. The exported cert needs to be installed on the client with read permissions for the service account. That's it!
Thank you Max for providing me with some direction.

Could not connect to AD ldaps from any other non-windows computer

I have 2 domain controllers, one is PDC and also with Root CA(not best practice) and dns. the other one is just a domain controller.
I have done all needed configuration for ldaps in the second domain controller and tested ldp working fine from both the workstation and the DC itself. however I could not connect to it from linux server.
when using openssl s_client -connect dc02.domainname:636 -showcerts. it always returned no peer certificate available.
CONNECTED(00000003)
write:errno=104
---
no peer certificate available
---
No client certificate CA names sent
---
SSL handshake has read 0 bytes and written 289 bytes
---
New, (NONE), Cipher is (NONE)
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
Protocol : TLSv1.2
Cipher : 0000
Session-ID:
Session-ID-ctx:
Master-Key:
Key-Arg : None
Krb5 Principal: None
PSK identity: None
PSK identity hint: None
Start Time: 1610484233
Timeout : 300 (sec)
Verify return code: 0 (ok)
---
Firewall and everything are OK since connection test are all good. I do know from where I can troubleshoot this problem as I can see certs are in computer store and service keystore.
Could someone provide me some hint as from where I can continue this troubleshooting and investigation?
Thanks.
This may depend on the permission of the cert that you are attempting to grab from the server you may want to add an everyone group and allow it to read-only or add the Linux Server to the domain via SSSD and then give the server access in the same menu. Also, ensure the cert you are attempting to push is publicly visible.
REF (How to add a Linux machine to AD): https://www.datasunrise.com/blog/professional-info/integrating-a-linux-machine-into-windows-active-directory-domain/
CA Properties
It turns out that port 88 is also needed when doing ldaps authentication and etc. when open port 88 for both tcp and udp, the test and everything works fine.
Thanks for the suggestions.

When is it necessary to provide a CA file?

I'm writing a server in Go that uses MongoDB and I was doing some research on how to enable SSL for the connection to the database. I found several examples that explain how to add the CA file. Like so:
mongo.NewClientWithOptions(connectionString, mongo.ClientOpt.SSLCaFile(caFilePath))
I'm using a hosted database on Atlas and they state that all connections use SSL by default. This answer on a different question shows how to connect to Atlas with Go but the code example doesn't use a CA file. I also couldn't find an option to download the CA file from Atlas that I could use.
This confuses me a bit and leads to the following questions. When is it necessary to provide a CA file like shown above to use SSL? If it's always required for SSL to provide a CA file, where do I get the CA file from to connect to a managed cluster on Atlas?
You always need a CA certificate to validate the server when initiating a TLS connection. Sometimes this is already installed on your platform and used automatically. You have to provide a CA file during connection when such a root certificate is not available. The CA file is used to validate the certificate presented by the server. A trusted third party provides this CA, and also (possibly through a chain of trusted parties) provides a certificate to the server, so you can validate the server is who claims it is by validating its certificate using the CA.
All platforms come with an initial set of root certificates that can validate well-known third-party generated certificates. The mongodb server you're connecting to is probably using such a certificate, and thus, your OS certificates can be used to validate it. If you had your own PKI with your own CA not validated by a third party, then you'd need a separate CA file signed by your own CA. Then you'd need to pass that CA file to validate the server, because your root certificate will not contain your custom CA.
The CA file specifies which self-signed root certificates you trust, and can include intermediate certificate authorities as well.
When the application connects to the server, the server sends its certificate as part of the handshake. The server's certificate was digitally signed.
In order to check that the server certificate was not tampered with, the issuer's certificate is consulted, which contains a public key that can be used to validate the digital signature.
If the issuer was an intermediate CA, then its certificate was also signed by another CA, so that CA's certificate will be consulted to validate the signature on the intermediate certificate.
This continues until the chain reaches a certificate that was signed by itself. This is the root certificate. Since it signs itself, you have to explicitly indicate that you trust it in order to trust the entire chain, including the server being connected to.
The bottom line here is you need to provide a CA file when:
You care about verifying the identity of the server you are connecting to (i.e. preventing man in the middle attacks), and
The root certificate will not already be trusted implicitly by inclusion in a local trust store

Identityserver4 - Hosting in IIS

How to host ASPNET CORE APP with IdentityServer4 in IIS. The app is running fine from localhost but not as a web application setup in IIS.
For Example,
http://localhost:5000/connect/token is working but http://example.com/myauthapp/connect/token is not reachable - returning 500 - internal server error when tried from a console app using identity model or via postman. I am able to login to the app using web browser but not thru a console app or postman.
Further Troubleshoot and I find the below.
An unhandled exception has occurred: IDX10638: Cannot created the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: Microsoft.IdentityModel.Tokens.RsaSecurityKey.
System.InvalidOperationException: IDX10638: Cannot created the SignatureProvider, 'key.HasPrivateKey' is false, cannot create signatures. Key: Microsoft.IdentityModel.Tokens.RsaSecurityKey.
at Microsoft.IdentityModel.Tokens.AsymmetricSignatureProvider..ctor(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at Microsoft.IdentityModel.Tokens.CryptoProviderFactory.CreateSignatureProvider(SecurityKey key, String algorithm, Boolean willCreateSignatures)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.CreateEncodedSignature(String input, SigningCredentials signingCredentials)
at System.IdentityModel.Tokens.Jwt.JwtSecurityTokenHandler.WriteToken(SecurityToken token)
at IdentityServer4.Services.DefaultTokenCreationService.CreateJwtAsync(JwtSecurityToken jwt)
at IdentityServer4.Services.DefaultTokenCreationService.<CreateTokenAsync>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
How can I solve this issue?
As Arun noted in his comment, the certificate has to be installed on the server.
1 . To test this on localhost first, make sure you are using "AddSigningCredential" not "AddTemporarySigningCredential".
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2(Path.Combine(_environment.ContentRootPath, "certs", "IdentityServer4Auth.pfx")));
//.AddTemporarySigningCredential()
;
Create the certificate in your project (create certs folder), running this in visual studio command:
"C:\Program Files (x86)\Windows Kits\8.1\bin\x64\makecert" -n
"CN=IdentityServer4Auth" -a sha256 -sv IdentityServer4Auth.pvk -r
IdentityServer4Auth.cer -b 01/01/2017 -e 01/01/2025
"C:\Program Files (x86)\Windows Kits\8.1\bin\x64\pvk2pfx" -pvk IdentityServer4Auth.pvk
-spc IdentityServer4Auth.cer -pfx IdentityServer4Auth.pfx
Test on localhost
If successful, deploy to iis server , install the certificate on the server by double clicking on it, and test.
Make sure the application pool "load user profile" is set to true :
Go to IIS Manager
Go to the application pool instance
Click advanced settings
Under Process model, set Load User Profile to true
Restart IIS
If this fails with a 500, like with me (and there is no logs to help you out), try this. To fix this recreate the certificate on the server the same way as in step 2 in the certs folder . double click the cert to install.
You might have to install the developer kit if you dont have visual studio installed:
https://developer.microsoft.com/en-us/windows/downloads/windows-8-1-sdk
A little background first, on why it is working on your Local Development computer and not running under IIS on a QA or Production Environment. If you are using Temporary Signing Credential when adding the service Identity Server 4 like so,
services.AddIdentityServer().AddTemporarySigningCredential();
Then you have to make sure the "User" that the "Process" is running as has a Private Key available for ID4 to create a Temporary Certificate. This is why the error message is
SignatureProvider, 'key.HasPrivateKey' is false, cannot create
signatures. Key: Microsoft.IdentityModel.Tokens.RsaSecurityKey.
In the case of Windows, this private key is generated by Windows automatically and can be found at the folder %APPDATA%\Microsoft\Crypto\RSA of the User or C:\Users\Username\AppData\Roaming\Microsoft\Crypto\RSA. The reason why this Private Key is missing is perhaps because the User that your Process is running as has never logged onto that Computer.
The likely SOLUTION in that case is to log in once as the User that will be running the Process on that Server. It is quite common for the Private Key directory to be missing if your Application Pool within IIS runs as a "non-service" user with very High Privileges and that user has never interactively logged onto the Server itself. This also explains why "localhost" works on your development computer, while running on a Production or QA Server may not.
More information on how and where Windows creates the Private Key for a User can be found here in this link Microsoft Key Storage and Retrieval. Also, it is recommended as mentioned by David Smit to explicitly specify a Private Key file, instead of using Temporary Signing Credentials. That is the cleaner solution if you are allowed to make code changes.
services.AddIdentityServer()
.AddSigningCredential(new X509Certificate2("C:\Certs\IdentityServer4PrivateKeyFile.pfx")));

Windows LDAP API: No connection over SSL

I’m trying to connect to an LDAP directory over SSL using the Windows LDAP C-API. This fails with error code 0x51 = LDAP_SERVER_DOWN while the event log on the client computer has this:
„The certificate received from the remote server does not contain the expected name. It is therefore not possible to determine whether we are connecting to the correct server. The server name we were expecting is eim-tsi2.sam.develop.beta.ads. The SSL connection request has failed. The attached data contains the server certificate.”
This is can’t be true since “Ldap Admin” is able to connect over SSL and port 636.
The LDAP directory is an Oracle DSEE which has the CA and the server certificate in the appropriate cert store.
The client has the CA installed in the “Trusted Root Certification Authorities” and there in the „Local Computer“ physical store. I assumed this to be the right place for the CA since my little client program uses the Windows LDAP C-API; LDAP Admin indeed expects the CA there.
Here is an excerpt of my program omitting the error handling and other obvious source code:
ld = ldap_sslinit(host, LDAP_SSL_PORT, 1);
// Set options: LDAP version, timeout ...
rc = ldap_set_option(ld, LDAP_OPT_SSL, LDAP_OPT_ON);
// Now connect:
rc = ldap_connect(ld, NULL);
Result:
0x51 = LDAP_SERVER_DOWN
Connecting without SSL succeeds so the LDAP server is generally accessible.
Since Ldap Admin is able to connect over SSL, I assume the certificates are valid and in the right place. But obviously the LDAP API expects them somewhere else and cannot get the server certificate from the server. I configured the certs as described here: https://msdn.microsoft.com/en-us/library/aa366105%28v=vs.85%29.aspx
What am I doing wrong?
Sometimes it helps reading error messages more carefully. The entry in the event viewer caused by an unsuccessful bind over SSL was "The server name we were expecting is eim-tsi2.sam.develop.beta.ads."
I should have noticed that the name should have been eim-tsi2.cgn.de.(etc.), instead. So the domain name part was wrong.
This is a bug in Schannel which can be solved by an entry in the registry as described here: https://support.microsoft.com/en-us/kb/2275950.
I still do not know why LDAPAdmin was able to connect without that additional registry key although it also uses the WINLDAP API and therefore should have run into the same error. But that doesn’t matter any more.
Thanks, Andrew, for your help.

Resources