File: System\DirectoryServices\Protocols\ldap\LdapException.cs
Web Access
Project: src\src\libraries\System.DirectoryServices.Protocols\src\System.DirectoryServices.Protocols.csproj (System.DirectoryServices.Protocols)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.Serialization;
 
namespace System.DirectoryServices.Protocols
{
    internal enum LdapError
    {
        IsLeaf = 0x23,
        InvalidCredentials = 49,
        // The following values are defined in the LDAP C API standard, and are used in Windows Winldap.h.
        // See https://tools.ietf.org/html/draft-ietf-ldapext-ldap-c-api-05
        // Servers built from OpenLDAP headers use negative numbers for some, as shown below.
        // See https://github.com/openldap/openldap/blob/70488c22bf69be2a2c84127692413b815d8f9044/include/ldap.h#L724-L749
        ServerDown = 0x51,            // -1 from OpenLDAP servers
        LocalError = 0x52,            // -2
        EncodingError = 0x53,         // -3
        DecodingError = 0x54,         // -4
        TimeOut = 0x55,               // -5
        AuthUnknown = 0x56,           // -6
        FilterError = 0x57,           // -7
        UserCancelled = 0x58,         // -8
        ParameterError = 0x59,        // -9
        NoMemory = 0x5a,              // -10
        ConnectError = 0x5b,          // -11
        NotSupported = 0x5c,          // -12
        NoResultsReturned = 0x5e,     // -13
        ControlNotFound = 0x5d,       // -14
        MoreResults = 0x5f,           // -15
        ClientLoop = 0x60,            // -16
        ReferralLimitExceeded = 0x61, // -17
        SendTimeOut = 0x70
    }
 
    internal static class LdapErrorMappings
    {
        private static readonly Dictionary<LdapError, string> s_resultCodeMapping = new Dictionary<LdapError, string>(capacity: 20)
        {
            { LdapError.IsLeaf, SR.LDAP_IS_LEAF },
            { LdapError.InvalidCredentials, SR.LDAP_INVALID_CREDENTIALS },
            { LdapError.ServerDown, SR.LDAP_SERVER_DOWN },
            { LdapError.LocalError, SR.LDAP_LOCAL_ERROR },
            { LdapError.EncodingError, SR.LDAP_ENCODING_ERROR },
            { LdapError.DecodingError, SR.LDAP_DECODING_ERROR },
            { LdapError.TimeOut, SR.LDAP_TIMEOUT },
            { LdapError.AuthUnknown, SR.LDAP_AUTH_UNKNOWN },
            { LdapError.FilterError, SR.LDAP_FILTER_ERROR },
            { LdapError.UserCancelled, SR.LDAP_USER_CANCELLED },
            { LdapError.ParameterError, SR.LDAP_PARAM_ERROR },
            { LdapError.NoMemory, SR.LDAP_NO_MEMORY },
            { LdapError.ConnectError, SR.LDAP_CONNECT_ERROR },
            { LdapError.NotSupported, SR.LDAP_NOT_SUPPORTED },
            { LdapError.NoResultsReturned, SR.LDAP_NO_RESULTS_RETURNED },
            { LdapError.ControlNotFound, SR.LDAP_CONTROL_NOT_FOUND },
            { LdapError.MoreResults, SR.LDAP_MORE_RESULTS_TO_RETURN },
            { LdapError.ClientLoop, SR.LDAP_CLIENT_LOOP },
            { LdapError.ReferralLimitExceeded, SR.LDAP_REFERRAL_LIMIT_EXCEEDED },
            { LdapError.SendTimeOut, SR.LDAP_SEND_TIMEOUT }
        };
 
        internal static int NormalizeResultCode(int errorCode)
        {
            // OpenLDAP codes -1 to -17 should map to 81 to 97 respectively;
            // See note above.
            return (errorCode <= -1 && errorCode >= -17) ? 80 - errorCode : errorCode;
        }
 
        public static string MapResultCode(int errorCode)
        {
            errorCode = NormalizeResultCode(errorCode);
            s_resultCodeMapping.TryGetValue((LdapError)errorCode, out string errorMessage);
            return errorMessage;
        }
 
        internal static bool IsLdapError(int errorCode)
        {
            LdapError error = (LdapError)NormalizeResultCode(errorCode);
            if (error == LdapError.IsLeaf || error == LdapError.InvalidCredentials || error == LdapError.SendTimeOut)
            {
                return true;
            }
 
            return (error >= LdapError.ServerDown && error <= LdapError.ReferralLimitExceeded);
        }
    }
 
    [Serializable]
    [System.Runtime.CompilerServices.TypeForwardedFrom("System.DirectoryServices.Protocols, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class LdapException : DirectoryException, ISerializable
    {
        private int _errorCode;
 
#if NET
        [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
        [EditorBrowsable(EditorBrowsableState.Never)]
#endif
        protected LdapException(SerializationInfo info, StreamingContext context) : base(info, context) { }
 
        public LdapException() : base() { }
 
        public LdapException(string message) : base(message) { }
 
        public LdapException(string message, Exception inner) : base(message, inner) { }
 
        public LdapException(int errorCode)
                : base(SR.Format(SR.DefaultLdapError, LdapErrorMappings.NormalizeResultCode(errorCode)))
        {
            ErrorCode = errorCode;
        }
 
        public LdapException(int errorCode, string message) : base(message)
        {
            ErrorCode = errorCode;
        }
 
        public LdapException(int errorCode, string message, string serverErrorMessage) : base(message)
        {
            ErrorCode = errorCode;
            ServerErrorMessage = serverErrorMessage;
        }
 
        public LdapException(int errorCode, string message, Exception inner) : base(message, inner)
        {
            ErrorCode = errorCode;
        }
 
        public int ErrorCode
        {
            get => _errorCode;
            private set
            {
                _errorCode = LdapErrorMappings.NormalizeResultCode(value);
            }
        }
 
        public string ServerErrorMessage { get; }
 
        public PartialResultsCollection PartialResults { get; } = new PartialResultsCollection();
    }
 
    [Serializable]
    [System.Runtime.CompilerServices.TypeForwardedFrom("System.DirectoryServices.Protocols, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")]
    public class TlsOperationException : DirectoryOperationException
    {
#if NET
        [Obsolete(Obsoletions.LegacyFormatterImplMessage, DiagnosticId = Obsoletions.LegacyFormatterImplDiagId, UrlFormat = Obsoletions.SharedUrlFormat)]
        [EditorBrowsable(EditorBrowsableState.Never)]
#endif
        protected TlsOperationException(SerializationInfo info, StreamingContext context) : base(info, context) { }
 
        public TlsOperationException() : base() { }
 
        public TlsOperationException(string message) : base(message) { }
 
        public TlsOperationException(string message, Exception inner) : base(message, inner) { }
 
        public TlsOperationException(DirectoryResponse response) : base(response)
        {
        }
 
        public TlsOperationException(DirectoryResponse response, string message) : base(response, message)
        {
        }
 
        public TlsOperationException(DirectoryResponse response, string message, Exception inner) : base(response, message, inner)
        {
        }
    }
 
    internal static class ErrorChecking
    {
        public static void CheckAndSetLdapError(int error)
        {
            if (error != (int)ResultCode.Success)
            {
                if (Utility.IsResultCode((ResultCode)error))
                {
                    string errorMessage = OperationErrorMappings.MapResultCode(error);
                    throw new DirectoryOperationException(null, errorMessage);
                }
                else if (LdapErrorMappings.IsLdapError(error))
                {
                    string errorMessage = LdapErrorMappings.MapResultCode(error);
                    throw new LdapException(error, errorMessage);
                }
                else
                {
                    throw new LdapException(error);
                }
            }
        }
    }
}