Esempio n. 1
0
        private async Task OnRequestAsync(LdapRequestMessage message, LdapClientConnection connection)
        {
            if (!await connection.TryAddPendingAsync(message).ConfigureAwait(false))
            {
                return;
            }
            try
            {
                if (message is LdapAbandonRequest abandon)
                {
                    connection.ContinueRead();
                    if (CriticalControlsSupported(abandon.Controls))
                    {
                        connection.AbandonRequest(abandon.MessageId);
                    }
                }
                else if (message is LdapBindRequest bind)
                {
                    connection.ContinueRead();
                    try
                    {
                        await connection.BeginBindAsync().ConfigureAwait(false);

                        var response = await BindRequestAsync(bind, connection).ConfigureAwait(false);
                        await WriteAsync(response, connection).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        await WriteAsync(bind.Response(ResultCode.Other, ex.Message), connection).ConfigureAwait(false);
                    }
                    finally
                    {
                        connection.FinishBind();
                    }
                }
                else if (message is LdapUnbindRequest)
                {
                    connection.ContinueRead();
                    UnbindRequest(connection);
                }
                else if (message is LdapSearchRequest search)
                {
                    connection.ContinueRead();
                    await SearchRequestAsync(search, connection).ConfigureAwait(false);
                }
                else if (message is LdapExtendedRequest extended)
                {
                    await ExtendedRequestAsync(extended, connection).ConfigureAwait(false);
                }
                else
                {
                    connection.ContinueRead();
                    throw new NotImplementedException();
                }
            }
            finally
            {
                connection.RemovePending(message);
            }
        }
Esempio n. 2
0
        private async Task SearchRequestAsync(LdapSearchRequest request, LdapClientConnection connection, CancellationToken cancellationToken)
        {
            try
            {
                if (request.BaseObject.RDNs.Count == 0 &&
                    request.Scope == SearchScope.BaseObject &&
                    request.Filter is LdapPresentFilter filter &&
                    (filter.Attribute.Oid.Equals("objectClass", StringComparison.OrdinalIgnoreCase) || filter.Attribute.Oid == "2.5.4.0"))
                {
                    ICollection <LdapAttribute> attributes = _rootDse.GetAttributes(request.Attributes, request.TypesOnly).ToList();
                    if (_sslOptions != null && request.Attributes.Where(x => x.Selector != null).Any(x => x.Selector.Oid == SupportedExtensionAttribute.OidValue || x.Selector.Oid == SupportedExtensionAttribute.ShortName))
                    {
                        var attribute = attributes.OfType <SupportedExtensionAttribute>().FirstOrDefault();
                        if (attribute == null)
                        {
                            attribute = new SupportedExtensionAttribute
                            {
                                Entries = { LdapExtendedRequest.StartTLS }
                            };
                            attributes.Add(attribute);
                        }
                        else
                        {
                            attribute.Entries.Add(LdapExtendedRequest.StartTLS);
                        }
                    }
                    attributes = await OnGetRootDSEAsync(attributes, connection, cancellationToken).ConfigureAwait(false);

                    var entry = request.Result(LdapDistinguishedName.Empty, attributes.ToArray(), Array.Empty <LdapControl>());
                    await WriteAsync(entry, connection).ConfigureAwait(false);
                    await WriteAsync(request.Done(), connection).ConfigureAwait(false);
                }
                else
                {
                    var results = await OnSearchAsync(request, connection, cancellationToken).ConfigureAwait(false);

                    bool done = false;
                    foreach (var response in results)
                    {
                        await WriteAsync(response, connection).ConfigureAwait(false);

                        if (response is LdapSearchResultDone)
                        {
                            done = true;
                            break;
                        }
                    }
                    if (!done)
                    {
                        await WriteAsync(request.Done(), connection).ConfigureAwait(false);
                    }
                }
            }
Esempio n. 3
0
        private async Task <LdapBindResponse> OnBindAsync(LdapBindRequest request, LdapClientConnection connection)
        {
            ResultCode result = ResultCode.AuthMethodNotSupported;

            if (request.Simple != null)
            {
                result = await OnBindAsync(request.Name, request.Simple.Value, connection).ConfigureAwait(false);
            }
            else if (request.SaslMechanism == SupportedSASLMechanismsAttribute.Anonymous)
            {
                var credentials = request.SaslCredentials.GetValueOrDefault(ReadOnlyMemory <byte> .Empty);
                result = await OnSaslBindAsync(request.Name, String.Empty, credentials, connection).ConfigureAwait(false);
            }
            else if (request.SaslMechanism == SupportedSASLMechanismsAttribute.Plain)
            {
                if (request.SaslCredentials == null)
                {
                    result = ResultCode.InappropriateAuthentication;
                }
                else
                {
                    var credentials = request.SaslCredentials.Value;
                    var first       = credentials.Span.IndexOf((byte)0);
                    var last        = credentials.Span.LastIndexOf((byte)0);
                    if (first == last)
                    {
                        result = ResultCode.InappropriateAuthentication;
                    }
                    else
                    {
                        first++;
                        var user     = Encoding.UTF8.GetString(credentials.Slice(first, last - first).Span);
                        var password = credentials.Slice(last + 1);
                        result = await OnSaslBindAsync(request.Name, user, password, connection).ConfigureAwait(false);
                    }
                }
            }
            switch (result)
            {
            case ResultCode.Other:
                return(request.Response(result, "Not implemented"));

            case ResultCode.Success:
                return(request.Response());

            default:
                return(request.Response(result, String.Empty));
            }
        }
Esempio n. 4
0
 private async Task SearchRequestAsync(LdapSearchRequest request, LdapClientConnection connection)
 {
     if (request.TimeLimit != TimeSpan.Zero)
     {
         using (var cts = new CancellationTokenSource(request.TimeLimit))
             using (var combined = CancellationTokenSource.CreateLinkedTokenSource(connection.CancellationToken, cts.Token))
             {
                 await SearchRequestAsync(request, connection, combined.Token).ConfigureAwait(false);
             }
     }
     else
     {
         await SearchRequestAsync(request, connection, connection.CancellationToken).ConfigureAwait(false);
     }
 }
Esempio n. 5
0
 private Task <LdapBindResponse> BindRequestAsync(LdapBindRequest request, LdapClientConnection connection)
 {
     if (request.Version != 3)
     {
         return(Task.FromResult(request.Response(ResultCode.ProtocolError, "only version 3 is supported")));
     }
     if (!CriticalControlsSupported(request.Controls))
     {
         return(Task.FromResult(request.Response(ResultCode.UnavailableCriticalExtension, String.Empty)));
     }
     if (request.Simple.HasValue && request.Simple.Value.Length == 0 && request.Name.RDNs.Count > 0)
     {
         //https://tools.ietf.org/html/rfc4513#section-5.1.2
         return(Task.FromResult(request.Response(ResultCode.UnwillingToPerform, "Unauthenticated Bind")));
     }
     if (request.SaslMechanism != null && request.SaslMechanism.Length == 0)
     {
         return(Task.FromResult(request.Response(ResultCode.AuthMethodNotSupported, "SASL aborted")));
     }
     return(OnBindAsync(request, connection));
 }
Esempio n. 6
0
 private static void UnbindRequest(LdapClientConnection connection)
 {
     connection.CloseConnection();
 }
Esempio n. 7
0
 protected virtual Task <LdapExtendedResponse> OnExtendedAsync(LdapExtendedRequest request, LdapClientConnection connection)
 {
     return(Task.FromResult(request.NotSupported()));
 }
Esempio n. 8
0
 protected virtual Task <ICollection <LdapAttribute> > OnGetRootDSEAsync(ICollection <LdapAttribute> attributes, LdapClientConnection connection, CancellationToken cancellationToken)
 {
     return(Task.FromResult(attributes));
 }
Esempio n. 9
0
 protected virtual Task <IEnumerable <LdapRequestMessage> > OnSearchAsync(LdapSearchRequest request, LdapClientConnection connection, CancellationToken cancellationToken)
 {
     return(Task.FromResult(Enumerable.Empty <LdapRequestMessage>()));
 }
Esempio n. 10
0
 protected virtual Task <ResultCode> OnSaslBindAsync(LdapDistinguishedName bindDN, string username, ReadOnlyMemory <byte> password, LdapClientConnection connection)
 {
     return(Task.FromResult(ResultCode.Other));
 }
Esempio n. 11
0
 protected virtual void OnError(LdapClientConnection connection, LdapException exception)
 {
     return;
 }