Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GSSAPI/Windows SASL authentication #28

Open
long2know opened this issue Jun 16, 2017 · 10 comments
Open

GSSAPI/Windows SASL authentication #28

long2know opened this issue Jun 16, 2017 · 10 comments

Comments

@long2know
Copy link

I was looking through the source code for LdapBindRequest and RfcBindRequest, and it doesn't appear to be any way to use the currently logged in Windows User for authentication in the case of connecting to an Active Directory server.

Is there any possibility of support this scenario? Ideally, I would like to run my .NET Core service as a specific user and let the that user's identity be used for the Ldap "bind" rather than storing username and password in my application's configuration.

@gfoidl
Copy link

gfoidl commented Jun 19, 2017

To my understanding this could be done via kerberos tickets, and a bind via GSSAPI. For later see issue #7.
So right now there is no possibility to do this. Unfortunately 😢

@dsbenghe
Copy link
Owner

@gfoidl is correct - this is how is supposed to work, but is not implemented.

@winnieryl
Copy link

@gfoidl is correct - this is how is supposed to work, but is not implemented.

Is this implemented in the latest code?

@vletoux
Copy link

vletoux commented Feb 1, 2019

the GSSAPI data can be produced on Windows with InitializeSecurityContext

The data provided by GSSAPI "just" need to be embedded into LDAP.

I can help:
I've a c code performing the authentication using GSSAPI and the code to answer manually a NTLM challenge/response (fallback)
https://github.com/vletoux/DetectPasswordViaNTLMInFlow/blob/master/DetectPasswordViaNTLMInFlow.cpp
InitializeSecurityContext is really painful to pinvoke but nothing impossible.

I can write a prototype to produce the GSSAPI data if someone is doing the LDAP part to embed it.

For linux, after some research, it seems that the API to use is gss_init_sec_context.
Unfortunately, I'm not a linux guy.

@lkspencer
Copy link

Have you looked at what's been done here? maybe something over there will help. That project's kerberos authentication does appear to work, at least in my simple tests.

@Evengard
Copy link
Contributor

Evengard commented Dec 28, 2020

Actually this library IS extensible enough to be able to implement your own SASL provider. I actually managed to implement auth into Ldap using Kerberos tickets via SPNEGO. Implementing InitializeSecurityContext may be actually even easier.

Just look at RegisterSaslClientFactory and the whole ISaslClientFactory/ISaslClient interfaces and their realization.

@dsbenghe dsbenghe changed the title Windows Authentication GSSAPI/Windows SASL authentication Dec 31, 2020
@lolligd
Copy link

lolligd commented Sep 16, 2022

Has there been any movement on this? Would love to know if anyone has a good pattern setup that actually implements this properly.

@ststeiger
Copy link

Hey guys, take a look at ldap4net:
https://github.com/flamencist/ldap4net#setoption
It has GSSAPI-support and works on Linux and Mac, too !


namespace ConsoleAdBrowser
{

    using LdapForNet;


    class Program
    {


        public static void GetAdController(out string url, out int port)
        {
            System.Net.NetworkInformation.IPGlobalProperties ipgp =
                System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties();

            // IDnsResolver resolver = new RecursiveDnsResolver(); // Warning: Doesn't work
            ARSoft.Tools.Net.Dns.IDnsResolver resolver = new ARSoft.Tools.Net.Dns.DnsStubResolver();

            string magicUrl = "_ldap._tcp." + ipgp.DomainName;

            System.Collections.Generic.List<ARSoft.Tools.Net.Dns.SrvRecord> srvRecords =
                resolver.Resolve<ARSoft.Tools.Net.Dns.SrvRecord>(
                    new ARSoft.Tools.Net.DomainName(magicUrl.Split('.')),
                    ARSoft.Tools.Net.Dns.RecordType.Srv
            );

            foreach (ARSoft.Tools.Net.Dns.SrvRecord thisRecord in srvRecords)
            {
                // System.Console.WriteLine(thisRecord.Name);
                System.Console.WriteLine(thisRecord.Target);
                System.Console.WriteLine(thisRecord.Port);

                // Note: OR LDAPS:// - but Novell doesn't want these parts anyway 
                url = thisRecord.Target.ToString();
                port = thisRecord.Port;
                return;
            } // Next thisRecord

            url = null;
            port = -1;
        } // End Sub GetAdController 


        public static string GetDefaultNamingContext(LdapConnection cnn)
        {
            // https://ldapwiki.com/wiki/RootDSE
            LdapEntry rootDse = cnn.GetRootDse();
            DirectoryAttribute attr = rootDse.DirectoryAttributes["defaultNamingContext"];

            return attr.GetValue<string>();
        }


        // https://github.com/flamencist/ldap4net#getRootDse
        // https://github.com/ststeiger/ldap4net
        static void Main(string[] args)
        {
            string ldapHost = null;
            int ldapPort = -1;


            GetAdController(out ldapHost, out ldapPort);


            using (LdapConnection cnn = new LdapConnection())
            {

                // connect use Domain Controller host from computer hostname and default port 389
                // Computer hostname - mycomp.example.com => DC host - example.com
                // cnn.Connect();
                cnn.Connect(ldapHost, ldapPort);
                // cnn.Connect("dc.example.com", 389);
                // cnn.Connect("dc.example.com", 636);


                // int ldapVersion = (int)LdapForNet.Native.Native.LdapVersion.LDAP_VERSION3;
                // cnn.SetOption(LdapForNet.Native.Native.LdapOption.LDAP_OPT_PROTOCOL_VERSION, ldapVersion);
                // cnn.SetOption(LdapForNet.Native.Native.LdapOption.LDAP_OPT_DEREF, 1);

                // https://learn.microsoft.com/en-us/troubleshoot/windows-server/identity/ldap-paged-queries-subordinate-referrals-not-chased
                // Note: If you are not getting results beyond the first page,
                // this could because subordinate referrals are turned on as explained here.
                // In that case, one option is to turn off subordinate referrals
                // (as described in option 3 in the link's suggested workarounds).
                // This can be done as follows:
                cnn.SetOption(LdapForNet.Native.Native.LdapOption.LDAP_OPT_REFERRALS, System.IntPtr.Zero);


                // bind using kerberos credential cache file
                cnn.Bind();
                // cnn.Bind(loginDN, password);
                // cnn.Bind(ldapVersion, loginDN, password);

                // System.Collections.Generic.IList<LdapEntry> entries =cnn.Search("dc=example,dc=com", "(objectClass=*)");


                string searchBase = GetDefaultNamingContext(cnn);
                string searchFilter = null;

                System.Collections.Generic.IList<LdapEntry> lsc = cnn.Search(searchBase,
                    searchFilter, null, LdapForNet.Native.Native.LdapSearchScope.LDAP_SCOPE_ONE);


                string authzId = cnn.WhoAmI().Result;
                System.Console.Write("== Who am i ? ");
                System.Console.Write(authzId);
                System.Console.WriteLine("! === ");


                // string authzId = await cnn.WhoAmI();


                foreach (LdapEntry thisEntry in lsc)
                {
                    System.Console.Write(" - ");
                    System.Console.WriteLine(thisEntry.Dn);

                    ListDetails(thisEntry).Wait();
                } // Next thisEntry 

            } // End Using cnn 

            System.Console.WriteLine(" --- Press any key to continue --- ");
        } // End Sub Main 



        private static string[] GetStringValues(DirectoryAttribute attribute)
        {
            System.Collections.Generic.List<string> ls = new System.Collections.Generic.List<string>();

            foreach (string stringValue in attribute.GetValues<string>())
            {
                ls.Add(stringValue);
            } // Next stringValue 

            string[] arr = ls.ToArray();
            ls.Clear();
            ls = null;

            return arr;
        }


        private static byte[][] GetByteValues(DirectoryAttribute attribute)
        {
            System.Collections.Generic.List<byte[]> ls = new System.Collections.Generic.List<byte[]>();

            foreach (byte[] bytesValue in attribute.GetValues<byte[]>())
            {
                ls.Add(bytesValue);
            } // Next bytesValue 

            byte[][] arr = ls.ToArray();
            ls.Clear();
            ls = null;

            return arr;
        }


        private static readonly uint[] _lookup32 = CreateLookup32();

        private static uint[] CreateLookup32()
        {
            var result = new uint[256];
            for (int i = 0; i < 256; i++)
            {
                string s = i.ToString("X2");
                result[i] = ((uint)s[0]) + ((uint)s[1] << 16);
            }
            return result;
        }

        private static string ByteArrayToHexViaLookup32(byte[] bytes)
        {
            var lookup32 = _lookup32;
            var result = new char[bytes.Length * 2];
            for (int i = 0; i < bytes.Length; i++)
            {
                var val = lookup32[bytes[i]];
                result[2 * i] = (char)val;
                result[2 * i + 1] = (char)(val >> 16);
            }

            return new string(result);
        }



        private static async System.Threading.Tasks.Task ListDetails(
             // System.Text.Json.Utf8JsonWriter jsonWriter,
            LdapEntry thisEntry)
        {

            try
            {
                foreach (DirectoryAttribute attribute in thisEntry.DirectoryAttributes)
                {
                    // jsonWriter.WriteStartObject();

                    string attributeName = attribute.Name;
                    string attributeVal = attribute.GetValue<string>();
                    byte[][] bvs = GetByteValues(attribute);
                    string[] svs = GetStringValues(attribute);

                    try
                    {
                        attributeVal = string.Join(System.Environment.NewLine, GetStringValues(attribute));
                    }
                    catch (System.Exception ex)
                    {
                        System.Console.WriteLine(ex.Message);
                    }


                    // This comes with MS-DirectoryService, but not with Novell-DirectoryService
                    // nTSecurityDescriptor System.__ComObject
                    // if ("nTSecurityDescriptor".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase))
                    // System.Console.WriteLine(attributeName);


                    if (
                        "objectGUID".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msExchMailboxGuid".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "mS-DS-ConsistencyGuid".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msDFSR-ReplicationGroupGuid".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                    )
                    {
                        string[] fo = new string[bvs.Length];

                        for (int i = 0; i < bvs.Length; ++i)
                        {
                            fo[i] = new System.Guid(bvs[i]).ToString();
                        }

                        attributeVal = string.Join(System.Environment.NewLine, fo);
                    }
                    else if (System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "objectSid"))
                    {
                        string[] fo = new string[bvs.Length];

                        for (int i = 0; i < bvs.Length; ++i)
                        {
                            // Windows-only ...
                            // System.Security.Principal.SecurityIdentifier sid = new System.Security.Principal.SecurityIdentifier(bvs[i], 0);
                            // fo[i] = sid.ToString();
                            fo[i] = SidConverter.ConvertSidToString(bvs[i]);
                        }

                        attributeVal = string.Join(System.Environment.NewLine, fo);
                    }
                    else if (
                           "msExchWhenMailboxCreated".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "dSCorePropagationData".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "whenCreated".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "whenChanged".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                    )
                    {
                        try
                        {
                            for (int i = 0; i < svs.Length; ++i)
                            {
                                System.DateTime result = System.DateTime.ParseExact(svs[i], "yyyyMMddHHmmss.0Z", System.Globalization.CultureInfo.InvariantCulture);
                                svs[i] = result.ToString("dd'.'MM'.'yyyy' 'HH':'mm':'ss") + " (" + svs[i] + ")";
                            }

                            attributeVal = string.Join(System.Environment.NewLine, svs);
                        }
                        catch (System.Exception ex)
                        {
                            attributeVal = ex.Message;
                        }

                    }
                    else if (
                        System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "userCertificate")
                    )
                    {
                        string[] fo = new string[bvs.Length];

                        for (int i = 0; i < bvs.Length; ++i)
                        {
                            System.Security.Cryptography.X509Certificates.X509Certificate cert = new System.Security.Cryptography.X509Certificates.X509Certificate(bvs[i]);
                            fo[i] = cert.ToString();
                        }

                        attributeVal = string.Join(System.Environment.NewLine, fo);
                    }
                    else if (
                           "mSMQSignCertificates".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "mSMQDigest".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "mSMQDigests".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)


                        || "msDS-GroupMSAMembership".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msDS-ManagedPasswordId".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "ManagedPasswordPreviousId".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "logonHours".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msExchMailboxSecurityDescriptor".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msDS-GenerationId".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "msDS-ManagedPasswordPreviousId".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                        || "samDomainUpdates".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                    )
                    {
                        string[] fo = new string[bvs.Length];

                        for (int i = 0; i < bvs.Length; ++i)
                        {
                            fo[i] = "0x" + ByteArrayToHexViaLookup32(bvs[i]);
                        }

                        attributeVal = string.Join(System.Environment.NewLine, fo);
                    }
                    else if (System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "msExchRemoteRecipientType"))
                    {
                        try
                        {
                            long lngSomeVersion = long.Parse(attributeVal, System.Globalization.CultureInfo.InvariantCulture);

                            string strVersion = lngSomeVersion.ToString();
                            // http://memphistech.net/?p=457
                            // https://blogs.technet.microsoft.com/johnbai/2013/09/11/o365-exchange-and-ad-how-msexchrecipientdisplaytype-and-msexchangerecipienttypedetails-relate-to-your-on-premises/

                            switch (lngSomeVersion)
                            {
                                case 1:
                                    strVersion = "ProvisionedMailbox (Cloud MBX)";
                                    break;
                                case 2:
                                    strVersion = "ProvisionedArchive (Cloud Archive)";
                                    break;
                                case 3:
                                    strVersion = "ProvisionedMailbox, ProvisionedArchive";
                                    // (mailbox provisioned in Cloud & Archive provisioned in Cloud)* either via EMC or new-remotemailbox cmd
                                    break;
                                case 4:
                                    strVersion = "Migrated mailbox from on-prem";
                                    break;
                                case 6:
                                    strVersion = "Migrated mailbox from on-prem, ProvisionedArchive in EXO";
                                    // (mailbox migrated from on-prem & archive provisioned in Cloud)
                                    break;
                                case 16:
                                    strVersion = "DeprovisionArchive";
                                    break;
                                case 20:
                                    strVersion = "DeprovisionArchive, Migrated";
                                    break;
                                case 32:
                                    strVersion = "RoomMailbox";
                                    break;
                                case 36:
                                    strVersion = "Migrated, RoomMailbox";
                                    break;
                                case 64:
                                    strVersion = "EquipmentMailbox";
                                    break;
                                case 68:
                                    strVersion = "Migrated, EquipmentMailbox";
                                    break;
                                case 96:
                                    strVersion = "SharedMailbox";
                                    break;
                                case 100:
                                    strVersion = "Migrated, Shared Mailbox in EXO";
                                    break;
                                default:
                                    strVersion = lngSomeVersion.ToString();
                                    break;
                            }

                            attributeVal = strVersion;
                        }
                        catch (System.Exception ex)
                        {
                            attributeVal = ex.Message;
                        }

                    }
                    else if (System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "msExchRecipientDisplayType"))
                    {
                        try
                        {
                            long lngSomeVersion = long.Parse(attributeVal, System.Globalization.CultureInfo.InvariantCulture);

                            string strVersion = lngSomeVersion.ToString();
                            // http://memphistech.net/?p=457

                            switch (lngSomeVersion)
                            {
                                case 0:
                                    strVersion = "MailboxUser";
                                    break;
                                case 1:
                                    strVersion = "DistrbutionGroup";
                                    break;
                                case 2:
                                    strVersion = "PublicFolder";
                                    break;
                                case 3:
                                    strVersion = "DynamicDistributionGroup";
                                    break;
                                case 4:
                                    strVersion = "Organization";
                                    break;
                                case 5:
                                    strVersion = "PrivateDistributionList";
                                    break;
                                case 6:
                                    strVersion = "RemoteMailUser";
                                    break;
                                case 7:
                                    strVersion = "ConferenceRoomMailbox";
                                    break;
                                case 8:
                                    strVersion = "EquipmentMailbox";
                                    break;
                                case 1073741824:
                                    strVersion = "ACLableMailboxUser";
                                    break;
                                case 1043741833:
                                    strVersion = "SecurityDistributionGroup";
                                    break;
                                case -2147483642:
                                    strVersion = "SyncedMailboxUser";
                                    break;
                                case -2147483391:
                                    strVersion = "SyncedUDGasUDG";
                                    break;
                                case -2147483386:
                                    strVersion = "SyncedUDGasContact";
                                    break;
                                case -2147483130:
                                    strVersion = "SyncedPublicFolder";
                                    break;
                                case -2147482874:
                                    strVersion = "SyncedDynamicDistributionGroup";
                                    break;
                                case -2147482106:
                                    strVersion = "SyncedRemoteMailUser";
                                    break;
                                case -2147481850:
                                    strVersion = "SyncedConferenceRoomMailbox";
                                    break;
                                case -2147481594:
                                    strVersion = "SyncedEquipmentMailbox";
                                    break;
                                case -2147481343:
                                    strVersion = "SyncedUSGasUDG";
                                    break;
                                case -2147481338:
                                    strVersion = "SyncedUSGasContact";
                                    break;
                                case -1073741818:
                                    strVersion = "ACLableSyncedMailboxUser";
                                    break;
                                case -1073740282:
                                    strVersion = "ACLableSyncedRemoteMailUser";
                                    break;
                                case -1073739514:
                                    strVersion = "ACLableSyncedUSGasContact";
                                    break;
                                case -1073739511:
                                    strVersion = "SyncedUSGasUSG";
                                    break;
                                default:
                                    strVersion = lngSomeVersion.ToString();
                                    break;
                            }

                            attributeVal = strVersion;
                        }
                        catch (System.Exception ex)
                        {
                            attributeVal = ex.Message; ;
                        }
                    }
                    else if (System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "msExchRecipientTypeDetails"))
                    {
                        try
                        {
                            long lngSomeVersion = long.Parse(attributeVal, System.Globalization.CultureInfo.InvariantCulture);
                            string strVersion = lngSomeVersion.ToString();
                            // http://memphistech.net/?p=457
                            // https://blogs.technet.microsoft.com/johnbai/2013/09/11/o365-exchange-and-ad-how-msexchrecipientdisplaytype-and-msexchangerecipienttypedetails-relate-to-your-on-premises/

                            switch (lngSomeVersion)
                            {

                                case 1:
                                    strVersion = "User Mailbox";
                                    break;
                                case 2:
                                    strVersion = "Linked Mailbox";
                                    break;
                                case 4:
                                    strVersion = "Shared Mailbox";
                                    break;
                                case 8:
                                    strVersion = "Legacy Mailbox";
                                    break;
                                case 16:
                                    strVersion = "Room Mailbox";
                                    break;
                                case 32:
                                    strVersion = "Equipment Mailbox";
                                    break;
                                case 64:
                                    strVersion = "Mail Contact";
                                    break;
                                case 128:
                                    strVersion = "Mail User";
                                    break;
                                case 256:
                                    strVersion = "Mail-Enabled Universal Distribution Group";
                                    break;
                                case 512:
                                    strVersion = "Mail-Enabled Non-Universal Distribution Group";
                                    break;
                                case 1024:
                                    strVersion = "Mail-Enabled Universal Security Group";
                                    break;
                                case 2048:
                                    strVersion = "Dynamic Distribution Group";
                                    break;
                                case 4096:
                                    strVersion = "Public Folder";
                                    break;
                                case 8192:
                                    strVersion = "System Attendant Mailbox";
                                    break;
                                case 16384:
                                    strVersion = "System Mailbox";
                                    break;
                                case 32768:
                                    strVersion = "Cross-Forest Mail Contact";
                                    break;
                                case 65536:
                                    strVersion = "User";
                                    break;
                                case 131072:
                                    strVersion = "Contact";
                                    break;
                                case 262144:
                                    strVersion = "Universal Distribution Group";
                                    break;
                                case 524288:
                                    strVersion = "Universal Security Group";
                                    break;
                                case 1048576:
                                    strVersion = "Non-Universal Group";
                                    break;
                                case 2097152:
                                    strVersion = "Disabled User";
                                    break;
                                case 4194304:
                                    strVersion = "Microsoft Exchange";
                                    break;
                                case 8388608:
                                    strVersion = "Arbitration Mailbox";
                                    break;
                                case 16777216:
                                    strVersion = "Mailbox Plan";
                                    break;
                                case 33554432:
                                    strVersion = "Linked User";
                                    break;
                                case 268435456:
                                    strVersion = "Room List";
                                    break;
                                case 536870912:
                                    strVersion = "Discovery Mailbox";
                                    break;
                                case 1073741824:
                                    strVersion = "Role Group";
                                    break;
                                case 2147483648L:
                                    strVersion = "Remote Mailbox";
                                    break;
                                case 137438953472L:
                                    strVersion = "Team Mailbox";
                                    break;
                                default:
                                    strVersion = lngSomeVersion.ToString();
                                    break;
                            }

                            attributeVal = strVersion;
                        }
                        catch (System.Exception ex)
                        {
                            attributeVal = ex.Message;
                        }

                    }
                    else if (System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "msExchVersion"))
                    {
                        try
                        {
                            long lngSomeVersion = long.Parse(attributeVal, System.Globalization.CultureInfo.InvariantCulture);
                            string strVersion = "";

                            // http://blogs.metcorpconsulting.com/tech/?p=1313
                            if (lngSomeVersion < 4535486012416L)
                            {
                                strVersion = "Exchange 2003 and earlier (" + lngSomeVersion.ToString() + ")";
                            }
                            else if (lngSomeVersion == 4535486012416L)
                            {
                                strVersion = "Exchange 2007 (4535486012416)";
                            }
                            else if (lngSomeVersion == 44220983382016L)
                            {
                                strVersion = "Exchange 2010 (44220983382016)";
                            }
                            else
                            {
                                strVersion = lngSomeVersion.ToString();
                            }

                            attributeVal = strVersion;
                        }
                        catch (System.Exception ex)
                        {
                            attributeVal = ex.Message;
                        }
                    }
                    else if ("lastLogon".Equals(attributeName, System.StringComparison.InvariantCultureIgnoreCase)
                           || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "lastLogoff")
                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "lastLogonTimestamp")

                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "pwdLastSet")
                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "badPasswordTime")
                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "lockoutTime")

                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "uSNCreated")
                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "uSNChanged")

                            || System.StringComparer.OrdinalIgnoreCase.Equals(attributeName, "accountExpires")

                        )
                    {
                        long lngSomeAdTime = long.Parse(attributeVal, System.Globalization.CultureInfo.InvariantCulture);

                        System.DateTime someAdTime = System.DateTime.MaxValue;

                        if (lngSomeAdTime == long.MaxValue || lngSomeAdTime <= 0 || System.DateTime.MaxValue.ToFileTime() <= lngSomeAdTime)
                        {
                            someAdTime = System.DateTime.MaxValue;
                        }
                        else
                        {
                            // someAdTime = System.DateTime.FromFileTime(lngSomeAdTime);
                            someAdTime = System.DateTime.FromFileTimeUtc(lngSomeAdTime).ToLocalTime();
                        }

                        attributeVal = someAdTime.ToString("dd.MM.yyyy HH:mm:ss");
                    }

                    System.Console.Write("   -- ");
                    System.Console.Write(attributeName);
                    System.Console.Write(":\t");
                    System.Console.WriteLine(attributeVal);

                    // jsonWriter.WriteString(attributeName, attributeVal);
                } // Whend 

                // jsonWriter.WriteEndObject();
            }
            catch (System.Exception ex)
            {
                System.Console.WriteLine(ex.Message);
            }

        } // End Task ListDetails


    } // End Class 


} // End Namespace 

@Evengard
Copy link
Contributor

Honestly, I like this library more, it is more easily extensible, doesn't have a dependency on a non-C# library and allows mixing with Kerberos.NET - and as a result authenticating with an already existing Kerberos TGT.

@ststeiger
Copy link

ststeiger commented Jan 17, 2023

@Evengard: Even then, seems to be based on the same base library as Novell.
So now you can look at how it's done and port the relevant bits into fully-managed code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

9 participants