0

I've got an application that needs to be able to use the windows authentication for either the local machine or a domain. Previously, I was using PrincipalContext.ValidateCredentials, and it was working fine at first, then it started randomly returning false for correct credentials. I looked at this question and saw that people were saying that if PrincipalContext.ValidateCredentials was under too heavy of a load, then it could start throwing exceptions, and I noticed elsewhere people were saying it was always returning false.

The question I linked suggested using LogonUser instead from the advapi32.dll library. That's fine, the only issue is that I'd like to be able to reliably break the PrincipalContext.ValidateCredentials call before saying another method will work. This code produced no errors and never returns false on the same system that was returning those false negatives. I'd like to break it so I can make sure that the LogonUser call isn't going to have the same issue.

using System;
using System.Collections.Generic;
using System.DirectoryServices.AccountManagement;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace TestAuthentication
{
    class Program
    {
        static void Main(string[] args)
        {
            var credentials = new Dictionary<string, string>
            {
                {"Developer","rfsdev"},
                {"Customer","password"},
                {"Content Builder", "password"},
            };
            bool isBroken = false;
            int maxTries = 10000;
            int currentTry = 0;
            while(!isBroken && currentTry < maxTries)
            {
                currentTry++;
                foreach(var kvp in credentials)
                {
                    isBroken = !AreCredentialsValid(kvp.Key, kvp.Value);
                    Console.WriteLine("Result from {0} and {1}: {2}", kvp.Key, kvp.Value, !isBroken);
                    if (isBroken)
                    {
                        Console.WriteLine("Found breaking case after {0} tries", currentTry);
                        break;
                    }
                }
            }
            Console.ReadLine();
        }

        protected static bool AreCredentialsValid(string username, string password)
        {
            bool isDomain = username.Contains("\\");
            string domain = isDomain ? username.Split(new char[] { '\\' })[0] : "";
            username = isDomain ? username.Split(new char[] { '\\' })[1] : username;
            bool credentialsValid = false;
            if (isDomain)
                using (PrincipalContext pc = new PrincipalContext(ContextType.Domain, domain))
                    credentialsValid = pc.ValidateCredentials(username, password);
            else
                using (PrincipalContext pc = new PrincipalContext(ContextType.Machine))
                    credentialsValid = pc.ValidateCredentials(username, password);
            return credentialsValid;
        }
    }
}
Community
  • 1
  • 1
nick
  • 2,833
  • 3
  • 34
  • 61
  • I am just curious as to why you need an external .dll to do basic PrincipalContext in .NET.. is there something I am missing here..? – MethodMan Sep 22 '14 at 20:59
  • @DJKRAZE the external is for when I switch it over to use the LogonUser call. I missed that when cleaning the code to post it. – nick Sep 22 '14 at 21:02
  • you can do that without the external using and or writing some small AD code but I will look at your code more in detail to see if I see any additional issues or possible causes.. – MethodMan Sep 22 '14 at 21:04
  • also wonder why you are using a Dictionary instead of a List to store this Dictionary objects if I am not mistaken will fail if you have duplicate keys I would recommend an array – MethodMan Sep 22 '14 at 21:17
  • @DJKRAZE This is just a test program who's one job is to try to break the `PrincipalContext.ValidateCredentials`. The only part of the code that is from the production code that was failing is the `AreCredentialsValid` call. Everything else is just setting up tests for the `AreCredentialsValid`. – nick Sep 22 '14 at 22:29

0 Answers0