Ignoring Certificate errors when doing AD search using DirectorySearcher - c#

I am trying to connect to the Active Directory in order to search for a user. The server that I am hosting on has a certificate problem and as a result, my code is not running on the testing server. I need a way to ignore certificate errors using DirectorySearcher class.
I tried to use LDAPConnection and added the following lines
connection.SessionOptions.SecureSocketLayer = true; connection.SessionOptions.VerifyServerCertificate = new VerifyServerCertificateCallback((con, cer) => true);
However I need to use the same however using DirectorySearcher and DirectoryEntry.
Does anyone has a way that can assist me???

Related

Azure.Identity.CredentialUnavailableException GetCertificate from AzureKeyVault using azure.Security.KeyVault.Certificates

I have an app which uses certificates ( Uploaded the cert) in Azure Azure KeyVault.
I am trying to use asp.net application 4.7 to connect to key vault and retrieve the application Certificate and the Secret associate with it
Previously I used Microsoft.Azure.KeyVault and KeyVaultClient in combination with GetCertificateAsync and GetSecretAsync to pull the certificate and its secret.
However I recognized that Microsoft.Azure.KeyVault is deprecated so i researched and I found That I should use Azure.Security.KeyVault.Certificates instead.
I wrote the below code
New Way:
using Azure.Security.KeyVault.Certificates;
public static X509Certificate2 GetCertificateFromVault(string keyVaultName, string certificateName)
{
var keyVaultUri = $"https://{keyVaultName}.vault.azure.net/";
var client = new CertificateClient(new Uri(keyVaultUri), new DefaultAzureCredential());
KeyVaultCertificateWithPolicy keyVaultCertificateWithPolicy = client.GetCertificate(certificateName);
return new X509Certificate2(keyVaultCertificateWithPolicy.Cer);
}
However I get error on calling client.GetCertificate(certificateName); in above code which is my new way
Here is the error
Multiple exceptions were encountered while attempting to authenticate. ---> Azure.Identity.CredentialUnavailableException: E
nvironmentCredential authentication unavailable. Environment variables are not fully configured. See the troubleshooting guide for more information.
https://aka.ms/azsdk/net/identity/environmentcredential/troubleshoot\r\n at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()\r\n
at Azure.Identity.CredentialDiagnosticScope.FailWrapAndThrow(Exception ex, String additionalMessage)\r\n at
Azure.Identity.EnvironmentCredential.d__12.MoveNext()\r\n
I have KeyVaultCertificateOfficer role and I can retrieve the certificates using my old way on the local machine so I am sure I do not have access issue.
I looked at developer guide it says that I need to create
environment variables for AZURE_CLIENT_ID, AZURE_CLIENT_SECRET, and AZURE_TENANT_ID
Is that the solution? I do not understand why? Do I need to do this on all my different environment like UAT and PROD and create these variables. I kind of dont like that so i think i missing something here.
If I absolutely need to create env variables also not sure what to use as
AZURE_CLIENT_SECRET as I use Certificate not secret for my App. I saw AZURE_CLIENT_CERTIFICATE_PATH but that is the path to pfx in local machine right which we do not want that.
Maybe my understanding is totally wrong I am not sure. So any guidance would be much appreciated!
Create a key Vault and certificate in azure
And we have chosen the same .Net4.7 Framework
Used the NuGet package "Azure.Security.KeyVault.Certificates
The below namspaces are used in the application
using Azure.Identity;
using Azure.Security.KeyVault.Certificates;
using System.Security.Cryptography.X509Certificates;
Below is the code used for fetching the certificates from azure
string certificateName = "TestCertificate";
var KeyVaultUri = #"https://KeyVaultName.vault.azure.net/";
var client = new CertificateClient(new Uri(KeyVaultUri), new DefaultAzureCredential());
KeyVaultCertificateWithPolicy keyVaultCertificateWithPolicy = client.GetCertificate(certificateName);
var res= new X509Certificate2(keyVaultCertificateWithPolicy.Cer);
Certificate details are fetched in below screens

Directory entry | Error when using Encryption or SSL

I'm trying to encrypt my Active Directory access with the following code:
// Already tried different paths (LDAP://domain.com, LDAPS://domain.com etc.)
string path = "LDAP://domain.com:636";
var ldapConnection = new DirectoryEntry(path, "loginName", "password");
ldapConnection.AuthenticationType = AuthenticationTypes.Secure; // Works perfectly
ldapConnection.AuthenticationType = AuthenticationTypes.Encryption; // Doesn't work
ldapConnection.AuthenticationType = AuthenticationTypes.SecureSocketsLayer; // Doesn't work
Both Authentication Types that doesn't work throw the same exception:
System.DirectoryServices.DirectoryServicesCOMException (0x8007052E):
The username or password is incorrect.
Firstly I saw that I'm missing a Certificate Server on my AD DS and installed it. But after installation I get the same error. I might need to install/configure more things. If so, then please share resources what needs to be done.
My questions: Do I need any prerequisites (e.x. on the AD DS) to be able to use AuthenticationTypes.Encryption or AuthenticationTypes.SecureSocketsLayer? Or do I need a different user for using this Authentication Types?
Any Help is greatly appreciated.
Try this:
ldapConnection.AuthenticationType = AuthenticationTypes.Secure | AuthenticationTypes.SecureSocketsLayer;
Secure defines the type of authentication that is used, whereas SecureSocketsLayer defines the type of connection. They serve different purposes, so they can be used together.
But really, you don't need to specify anything. The default is Secure, and if you specify port 636, it will use SSL since that's the only way the server would accept the connection on that port. That's why it works when you only specify Secure.
That's also the reason it fails if you specify SecureSocketsLayer by itself. Once you specify anything, the default (Secure) is discarded and only what you specify is used. Without Secure it will try basic authentication (AKA "simple bind"), which is probably disabled on your domain.
More reading in the documentation for the AuthenticationTypes Enum.

Connecting or Accessing Okta LDAP Interface using c# .NET Client

I have a client which uses Okta LDAP Interface facility. We have a LDAP v3 tool which connects with AD, Open LDAP other LDAP v3 supported servers.
We want to integrate Okta LDAP Interface into our tool as it is LDAPv3 Compatible. Our Code is based on .NET framework + C Sharp.
We are facing some issues/challenges while connecting with Okta LDAP Interface.
We use System.DirectoryServices by Microsoft library provided by microsoft currently. But facing issues with LDAP Interface.
For StartTLS/389
I get the error :
Unwilling to perform. LDAP Error Code 53
More: A secure connection cannot be established. To admin: This service requires TLS. LDAP
For SSL/636
Error: The server is not operational.
Links:
https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices?view=netframework-4.8
https://learn.microsoft.com/en-us/dotnet/api/system.directoryservices.directoryentry?view=netframework-4.8
https://ldapwiki.com/wiki/LDAP_UNWILLING_TO_PERFORM
var oktaLDAPPath = "LDAP://dev-506668.ldap.oktapreview.com:636/ou=users,dc=dev-506668,dc=oktapreview,dc=com";
var un = "uid=*******,dc=dev-506668,dc=oktapreview,dc=com";
var pass = "*******";
var filter = "((objectClass=*))";
try
{
using (var userDirectoryEntry = new DirectoryEntry(oktaLDAPPath, un, pass,AuthenticationTypes.SecureSocketsLayer))
{
using (var directorySearcher = new DirectorySearcher(userDirectoryEntry, filter) { PageSize = 100 })
{
directorySearcher.FindOne();
}
}
}
catch (DirectoryServicesCOMException dex)
{
}
catch (Exception ex)
{
}
Thanks
Update: So I did some testing for myself. I see what's going on.
If you do a DNS lookup on dev-506668.ldap.oktapreview.com, it gives you a CNAME result to op1-ldapi-fb96b0a1937080bd.elb.us-east-1.amazonaws.com.
A browser will use the IP address of the CNAME, but still make the request with the host name that you originally gave it. However, for some reason, when starting an LDAP connection, Windows is using the CNAME to iniatate the connection.
In other words, Windows is changing the request to LDAP://op1-ldapi-fb96b0a1937080bd.elb.us-east-1.amazonaws.com:636. But then it receives the SSL certificate which has the name *.ldap.oktapreview.com and it panics because that doesn't match the name it used to make the request (op1-ldapi-fb96b0a1937080bd.elb.us-east-1.amazonaws.com).
I verified all of this using Wireshark, monitoring traffic on port 636. The SSL Client Hello is using op1-ldapi-fb96b0a1937080bd.elb.us-east-1.amazonaws.com instead of dev-506668.ldap.oktapreview.com.
I don't know of a way to make it not do that. DirectoryEntry has no way to override how it verifies the SSL certificate either. LdapConnection does, which you can see here, but it might be a little harder to work with. I've never used it. (you probably should do some verification of your own and no just return true like that example does).
This might be something you can share with Okta Support anyway.
Original answer:
It sounds like your computer does not trust the SSL certificate that is used on the server. To verify this, I use Chrome. You have to start Chrome like this:
chrome.exe --explicitly-allowed-ports=636
Then you can put this in the address bar:
https://dev-506668.ldap.oktapreview.com:636
If the certificate is not trusted, you will get a big error saying so. You can click the 'Advanced' button to see the reason Chrome gives for it not being trusted. But Chrome will also let you inspect the certificate by clicking on "Not secure" in the address bar to the left of the address, then click 'Certificate'.
There a couple reasons it might not be trusted:
The fully-qualified domain name you are using (dev-506668.ldap.oktapreview.com) doesn't match what is on the certificate. If that's the case, you might be able to just change the domain name you use to match the certificate.
The certificate is not issued by a trusted authority. It could be a self-signed certificate. If this is the case, then you should see an "Install Certificate" button when you view the certificate, which you can use to explicitly trust the certificate. See here for screenshots, starting on step 3. This will only apply to the current computer.
I recently ran into this issue and was pointed to the following solution:
Add the following registry value then restart the server and see if it fixes the issue.
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LDAP\UseHostnameAsAlias
DWORD, set the value to 1
See https://support.microsoft.com/en-us/topic/an-error-occurs-when-you-try-to-establish-ssl-connections-to-the-nodes-by-using-the-alias-name-from-an-ldaps-client-computer-that-is-running-windows-7-or-windows-server-2008-r2-49b6ee93-2c68-a892-8133-612d208dd1b1 for more details.

Create a user on a remote machine using c#

i am trying to create an app, which automatically creates and configures merge replication between the 2 PCs in the same local network.
To achieve this, i need to programaticaly create one user on each of the two PCs, this user should have exactly the same user name and passwords as it is required by the replication.
There is no DOMAIN on the network.
I did everything using GUI on both machines and replication works, now i need to do this using a C#. The replication part is done using SQL server 2012 RMO and SMO SDKs.
While googling, i found this (and many many other results which are more or less identical to this). But i believe, that these all examples are meant for local PCs, as it seems people were not getting errors like i do.
My sample code is:
DirectoryEntry directoryEntry = new DirectoryEntry(#"WinNT://WORKGROUP/WIN7-PC,computer", #"admin", "123456");
DirectoryEntry user = directoryEntry.Children.Add("RepTest", "user");
user.Invoke("SetPassword", new object[] { "rep123" });
user.CommitChanges();
I get an error at user.CommitChanges() saying that Access is denied, so i figured i had made a mistake in the authentication details provided to new DirectoryEntry(.... I fixed that and tried again:
DirectoryEntry directoryEntry = new DirectoryEntry(#"WinNT://WORKGROUP/WIN7-PC,computer", #"win7-pc\admin", "123456");
DirectoryEntry user = directoryEntry.Children.Add("RepTest", "user");
user.Invoke("SetPassword", new object[] { "rep123" });
user.CommitChanges();
Now I get the error on the line of .Children.Add(... stating that Multiple connections to a server or shared resource by the same user, using more than one user name, are not allowed.
When the first time i did it, i checked the Path of user object, which was WinNT://WORKGROUP/WIN7-PC/RepTest, not sure if it has anything to do with anything, but maybe it is trying to use the yet to be created new user folder while being connected as admin user?
Is there a way to get this thing going?

Creating local users on remote windows server using c#

Provided I have admin access, I need a way to manage (Create, modify, remove) local accounts in a remote machine from an ASP.NET client.
I'm clueless in how to approach this. Is WMI a possibility (System.Management namespace)?
Any pointers?
Give this a try:
DirectoryEntry directoryEntry = new DirectoryEntry("WinNT://ComputerName" & ",computer", "AdminUN", "AdminPW");
DirectoryEntry user = directoryEntry.Children.Add("username", "user");
user.Invoke("SetPassword", new object[] { "password"});
ser.CommitChanges();
If you do need to go the Active Directory route, you can change the directoryEntry path string to something like this: LDAP://CN=ComputerName,DC=MySample,DC=com
I used System.DirectoryServices to get data from users in a n ActiveDirectory (LDAP).
I don't know if that's the kind of thing you're looking for.
Hope it helps.
You should be able to do this via DirectoryEntry.

Categories