/// <summary>
        /// Creates a SearchResultReference. For LDAP v3 only.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="referenceUrls">The referenced URL.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultReferencePacket CreateSearchResultReference(
            AdtsLdapContext context,
            string[] referenceUrls)
        {
            int length = (referenceUrls != null) ? referenceUrls.Length : 0;

            LDAPURL[] ldapUrlArray = new LDAPURL[length];
            for (int i = 0; i < length; i++)
            {
                ldapUrlArray[i] = new LDAPURL(referenceUrls[i]);
            }
            SearchResultReference reference = new SearchResultReference(ldapUrlArray);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.searchResRef, reference);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultReferencePacket packet = new AdtsSearchResultReferencePacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates an ExtendedRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="requestName">The request name of the extended operation.</param>
        /// <param name="requestValue">The request value of the extended operation.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsExtendedRequestPacket CreateExtendedRequest(
            AdtsLdapContext context,
            string requestName,
            byte[] requestValue)
        {
            ExtendedRequest extendedRequest = new ExtendedRequest(
                new LDAPOID(requestName ?? string.Empty),
                new Asn1OctetString(requestValue));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.extendedReq, extendedRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsExtendedRequestPacket packet = new AdtsExtendedRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
예제 #3
0
        /// <summary>
        /// create sasl bind response packet.
        /// </summary>
        /// <param name="context">
        /// an AdtsLdapContext object that indicates the context of LDAP.
        /// </param>
        /// <param name="securityContext">
        /// a ServerSecurityContext object that specifies the security provider.
        /// </param>
        /// <param name="enableMessageSecurity">
        /// a bool value that indicates whether enable message security.
        /// </param>
        /// <returns>
        /// a BindResponsePacket object that responses the SASL bind request.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when context is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when securityContext is null.
        /// </exception>
        public AdtsBindResponsePacket CreateSaslBindResponse(
            AdtsLdapContext context, ServerSecurityContext securityContext, bool enableMessageSecurity)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (securityContext == null)
            {
                throw new ArgumentNullException("securityContext");
            }

            if (context.Security == null)
            {
                context.Security             = new AdtsLdapSaslSecurityLayer(securityContext);
                context.UsingMessageSecurity = enableMessageSecurity;
            }

            ResultCode resultCode = ResultCode.Success;

            if (securityContext.NeedContinueProcessing)
            {
                resultCode = ResultCode.SaslBindInProgress;
            }

            return(this.CreateBindResponse(
                       context, resultCode,
                       string.Empty, string.Empty, null, securityContext.Token));
        }
        /// <summary>
        /// create sasl bind response packet.
        /// </summary>
        /// <param name="context">
        /// an AdtsLdapContext object that indicates the context of LDAP.
        /// </param>
        /// <param name="securityContext">
        /// a ServerSecurityContext object that specifies the security provider.
        /// </param>
        /// <param name="enableMessageSecurity">
        /// a bool value that indicates whether enable message security.
        /// </param>
        /// <returns>
        /// a BindResponsePacket object that responses the SASL bind request.
        /// </returns>
        /// <exception cref="ArgumentNullException">
        /// thrown when context is null.
        /// </exception>
        /// <exception cref="ArgumentNullException">
        /// thrown when securityContext is null.
        /// </exception>
        public AdtsBindResponsePacket CreateSaslBindResponse(
            AdtsLdapContext context, ServerSecurityContext securityContext, bool enableMessageSecurity)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            if (securityContext == null)
            {
                throw new ArgumentNullException("securityContext");
            }

            if (context.Security == null)
            {
                context.Security = new AdtsLdapSaslSecurityLayer(securityContext);
                context.UsingMessageSecurity = enableMessageSecurity;
            }

            ResultCode resultCode = ResultCode.Success;

            if (securityContext.NeedContinueProcessing)
            {
                resultCode = ResultCode.SaslBindInProgress;
            }

            return this.CreateBindResponse(
                context, resultCode,
                string.Empty, string.Empty, null, securityContext.Token);
        }
예제 #5
0
 /// <summary>
 /// Creates a BindResponse for normal bindings and SASL bindings.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
 /// <param name="matchedDn">Matched DN. Required, but can be an empty string.</param>
 /// <param name="errorMessage">Error message for result code. Required.</param>
 /// <param name="referral">Referral. Optional and for LDAP v3 only.</param>
 /// <param name="serverCredentials">Server credentials, optional for normal bind.</param>
 /// <returns>The packet that contains the response.</returns>
 internal abstract AdtsBindResponsePacket CreateBindResponse(
     AdtsLdapContext context,
     ResultCode resultCode,
     string matchedDn,
     string errorMessage,
     string[] referral,
     byte[] serverCredentials);
예제 #6
0
        /// <summary>
        /// Creates an AddRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be added.</param>
        /// <param name="attributes">Attributes to be set.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAddRequestPacket CreateAddRequest(
            AdtsLdapContext context,
            string objectDn,
            params KeyValuePair <string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            AttributeList_element[] attributeArray = new AttributeList_element[length];
            for (int i = 0; i < length; i++)
            {
                AttributeValue[] attributeValues = new AttributeValue[attributes[i].Value.Length];
                for (int j = 0; j < attributes[i].Value.Length; i++)
                {
                    attributeValues[j] = new AttributeValue(attributes[i].Value[j]);
                }
                attributeArray[i] = new AttributeList_element(new AttributeDescription(attributes[i].Key), new Asn1SetOf <AttributeValue>(attributeValues));
            }

            AddRequest addRequest = new AddRequest(
                new LDAPDN(objectDn ?? string.Empty),
                new AttributeList(attributeArray));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.extendedReq, addRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);

            AdtsAddRequestPacket packet = new AdtsAddRequestPacket();

            packet.ldapMessagev3 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
 /// <summary>
 /// Creates a BindResponse for normal bindings and SASL bindings.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
 /// <param name="matchedDn">Matched DN. Required, but can be an empty string.</param>
 /// <param name="errorMessage">Error message for result code. Required.</param>
 /// <param name="referral">Referral. Optional and for LDAP v3 only.</param>
 /// <param name="serverCredentials">Server credentials, optional for normal bind.</param>
 /// <returns>The packet that contains the response.</returns>
 internal abstract AdtsBindResponsePacket CreateBindResponse(
     AdtsLdapContext context,
     ResultCode resultCode,
     string matchedDn,
     string errorMessage,
     string[] referral,
     byte[] serverCredentials);
        /// <summary>
        /// Creates an AddRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be added.</param>
        /// <param name="attributes">Attributes to be set.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAddRequestPacket CreateAddRequest(
            AdtsLdapContext context,
            string objectDn,
            params KeyValuePair<string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            AddRequest_attrs_element[] addrequestAttrsArray = new AddRequest_attrs_element[length];
            for (int i = 0; i < length; i++)
            {
                addrequestAttrsArray[i] = new AddRequest_attrs_element(
                    new AttributeType(attributes[i].Key),
                    CreateAttributeValueSet(attributes[i].Value));
            }
            Asn1SequenceOf<AddRequest_attrs_element> attributeList = new Asn1SequenceOf<AddRequest_attrs_element>(addrequestAttrsArray);

            AddRequest addRequest = new AddRequest(
                new LDAPDN(objectDn ?? string.Empty),
                attributeList);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.addRequest, addRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation);

            AdtsAddRequestPacket packet = new AdtsAddRequestPacket();
            packet.ldapMessagev2 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a SearchResultEntry packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="matchedDn">Matched DN.</param>
        /// <param name="attributes">The attributes and values that are contained in the entry.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultEntryPacket CreateSearchedResultEntry(
            AdtsLdapContext context,
            string matchedDn,
            params KeyValuePair <string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            SearchResponse_entry_attributes_element[] attributesElementArray = new SearchResponse_entry_attributes_element[length];
            for (int i = 0; i < length; i++)
            {
                attributesElementArray[i] = new SearchResponse_entry_attributes_element(
                    new AttributeType(attributes[i].Key),
                    CreateAttributeValueSet(attributes[i].Value));
            }
            Asn1SequenceOf <SearchResponse_entry_attributes_element> attributesElements = new Asn1SequenceOf <SearchResponse_entry_attributes_element>(attributesElementArray);

            SearchResponse_entry entry = new SearchResponse_entry(
                new LDAPDN(matchedDn ?? string.Empty),
                attributesElements);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.searchResponse, new SearchResponse(SearchResponse.entry, entry));

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsSearchResultEntryPacket packet = new AdtsSearchResultEntryPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
예제 #10
0
        /// <summary>
        /// Creates a SearchResultReference. For LDAP v3 only.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="referenceUrls">The referenced URL.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultReferencePacket CreateSearchResultReference(
            AdtsLdapContext context,
            string[] referenceUrls)
        {
            int length = (referenceUrls != null) ? referenceUrls.Length : 0;

            LDAPURL[] ldapUrlArray = new LDAPURL[length];
            for (int i = 0; i < length; i++)
            {
                ldapUrlArray[i] = new LDAPURL(referenceUrls[i]);
            }
            SearchResultReference reference = new SearchResultReference(ldapUrlArray);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.searchResRef, reference);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultReferencePacket packet = new AdtsSearchResultReferencePacket();

            packet.ldapMessagev3 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
예제 #11
0
        /// <summary>
        /// Creates a SearchResultDone packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="matchedDn">Matched DN.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <param name="referral">Referral. Optional.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultDonePacket CreateSearchResultDone(
            AdtsLdapContext context,
            MsLdap.ResultCode resultCode,
            string matchedDn,
            string errorMessage,
            string[] referral)
        {
            SearchResultDone searchResultDone = new SearchResultDone(
                new LDAPResult_resultCode((long)resultCode),
                new LDAPDN(matchedDn ?? string.Empty),
                new LDAPString(errorMessage ?? string.Empty),
                CreateReferral(referral));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.searchResDone, searchResultDone);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultDonePacket packet = new AdtsSearchResultDonePacket();

            packet.ldapMessagev3 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
        /// <summary>
        /// Creates an AddRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be added.</param>
        /// <param name="attributes">Attributes to be set.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAddRequestPacket CreateAddRequest(
            AdtsLdapContext context,
            string objectDn,
            params KeyValuePair <string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            AddRequest_attrs_element[] addrequestAttrsArray = new AddRequest_attrs_element[length];
            for (int i = 0; i < length; i++)
            {
                addrequestAttrsArray[i] = new AddRequest_attrs_element(
                    new AttributeType(attributes[i].Key),
                    CreateAttributeValueSet(attributes[i].Value));
            }
            Asn1SequenceOf <AddRequest_attrs_element> attributeList = new Asn1SequenceOf <AddRequest_attrs_element>(addrequestAttrsArray);

            AddRequest addRequest = new AddRequest(
                new LDAPDN(objectDn ?? string.Empty),
                attributeList);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.addRequest, addRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation);

            AdtsAddRequestPacket packet = new AdtsAddRequestPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
        /// <summary>
        /// Creates a ModifyDNRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="oldDn">The original DN to be modified.</param>
        /// <param name="newRdn">The new relative DN.</param>
        /// <param name="newParentDn">
        /// The new parent DN. For LDAP v3 only. Ignored when creating LDAP v2 requests.
        /// </param>
        /// <param name="delOldRdn">
        /// Whether to delete old RDN. For LDAP v3 only. Ignored when creating LDAP v2 requests.
        /// </param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsModifyDnRequestPacket CreateModifyDnRequest(
            AdtsLdapContext context,
            string oldDn,
            string newRdn,
            string newParentDn,
            bool delOldRdn)
        {
            ModifyDNRequest modifyDnRequest = new ModifyDNRequest(
                new LDAPDN(oldDn ?? string.Empty),
                new RelativeLDAPDN(newRdn ?? string.Empty),
                new Asn1Boolean(delOldRdn),
                new LDAPDN(newParentDn));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.modifyDNRequest, modifyDnRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsModifyDnRequestPacket packet = new AdtsModifyDnRequestPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
 /// <summary>
 /// Creates a BindRequest with SASL bind. This method is for LDAP v3 only.
 /// Note that for GSS-SPNEGO with NTLM, two rounds of bind requests is required.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="mechanism">Authentication mechanism used, e.g., GSS-SPNEGO, etc.</param>
 /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
 /// <returns>The packet that contains the request.</returns>
 internal override AdtsBindRequestPacket CreateSaslBindRequest(
     AdtsLdapContext context,
     string mechanism,
     byte[] credential)
 {
     throw new NotSupportedException();
 }
 /// <summary>
 /// Creates an ExtendedRequest packet.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="requestName">The request name of the extended operation.</param>
 /// <param name="requestValue">The request value of the extended operation.</param>
 /// <returns>The packet that contains the request.</returns>
 internal override AdtsExtendedRequestPacket CreateExtendedRequest(
     AdtsLdapContext context,
     string requestName,
     byte[] requestValue)
 {
     throw new NotSupportedException();
 }
        /// <summary>
        /// Creates a BindResponse for normal bindings, SASL bindings and sicily bindings.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="matchedDn">Matched DN. Required, but can be an empty string.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <param name="referral">Referral. Optional and for LDAP v3 only.</param>
        /// <param name="serverCredentials">Server credentials, optional for normal bind.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsBindResponsePacket CreateBindResponse(
            AdtsLdapContext context,
            MsLdap.ResultCode resultCode,
            string matchedDn,
            string errorMessage,
            string[] referral,
            byte[] serverCredentials)
        {
            BindResponse bindResponse = new BindResponse(
                new LDAPResult_resultCode((long)resultCode),
                new LDAPDN(matchedDn ?? string.Empty),
                new LDAPString(errorMessage ?? string.Empty));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.bindResponse, bindResponse);

            LDAPMessage            message = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsBindResponsePacket packet  = new AdtsBindResponsePacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
        /// <summary>
        /// Creates a ModifyRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of object to be modified.</param>
        /// <param name="modificationList">Modification list of attributes.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsModifyRequestPacket CreateModifyRequest(
            AdtsLdapContext context,
            string objectDn,
            params MsLdap.DirectoryAttributeModification[] modificationList)
        {
            int length = (modificationList != null) ? modificationList.Length : 0;

            ModifyRequest_modifications_element[] modifyRequestArray = new ModifyRequest_modifications_element[length];
            for (int i = 0; i < length; i++)
            {
                modifyRequestArray[i] = new ModifyRequest_modifications_element(
                    new ModifyRequest_modifications_element_operation((long)modificationList[i].Operation),
                    new ModifyRequest_modifications_element_modification(
                        new AttributeType(modificationList[i].Name),
                        CreateAttributeValueSet((string[])modificationList[i].GetValues(typeof(string)))));
            }
            Asn1SequenceOf <ModifyRequest_modifications_element> modificationSequence = new Asn1SequenceOf <ModifyRequest_modifications_element>(modifyRequestArray);

            ModifyRequest modifyRequest = new ModifyRequest(
                new LDAPDN(objectDn ?? string.Empty),
                modificationSequence);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.modifyRequest, modifyRequest);

            LDAPMessage             message = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsModifyRequestPacket packet  = new AdtsModifyRequestPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
예제 #18
0
 /// <summary>
 /// Creates a ModifyDnResponse packet.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
 /// <param name="matchedDn">Matched DN.</param>
 /// <param name="errorMessage">Error message for result code. Required.</param>
 /// <param name="referral">Referral. Optional. Used for LDAP v3 only.</param>
 /// <returns>The packet that contains the response.</returns>
 public AdtsModifyDnResponsePacket CreateModifyDnResponse(
     AdtsLdapContext context,
     ResultCode resultCode,
     string matchedDn,
     string errorMessage,
     string[] referral)
 {
     if (context.ServerVersion == AdtsLdapVersion.V2)
     {
         return(this.encoderv2.CreateModifyDnResponse(
                    context,
                    resultCode,
                    matchedDn,
                    errorMessage,
                    referral));
     }
     else
     {
         return(this.encoderv3.CreateModifyDnResponse(
                    context,
                    resultCode,
                    matchedDn,
                    errorMessage,
                    referral));
     }
 }
예제 #19
0
        /// <summary>
        /// Creates a BindResponse for normal bindings, SASL bindings and sicily bindings.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="matchedDn">
        /// Matched DN. Required for normal bindings, SASL bindings; but optional for sicily bind.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <param name="referral">Referral. Optional and for LDAP v3 only.</param>
        /// <param name="serverCredentials">Server credentials, optional for normal and sicily bind.</param>
        /// <returns>The packet that contains the response.</returns>
        public AdtsBindResponsePacket CreateBindResponse(
            AdtsLdapContext context,
            ResultCode resultCode,
            string matchedDn,
            string errorMessage,
            string[] referral,
            byte[] serverCredentials)
        {
            if (context.Security == null)
            {
                context.Security = new AdtsLdapSimpleSecurityLayer();
            }

            if (context.ServerVersion == AdtsLdapVersion.V2)
            {
                return(this.encoderv2.CreateBindResponse(
                           context,
                           resultCode,
                           matchedDn,
                           errorMessage,
                           referral,
                           serverCredentials));
            }
            else
            {
                return(this.encoderv3.CreateBindResponse(
                           context,
                           resultCode,
                           matchedDn,
                           errorMessage,
                           referral,
                           serverCredentials));
            }
        }
예제 #20
0
        /// <summary>
        /// Expects a packet.
        /// </summary>
        /// <param name="timeout">The timeout to be waited.</param>
        /// <param name="context">The context to be returned.</param>
        /// <returns>The packet received.</returns>
        public AdtsLdapPacket ExpectPacket(TimeSpan timeout, out AdtsLdapContext context)
        {
            while (true)
            {
                TransportEvent transportEvent = this.transportStack.ExpectTransportEvent(timeout);
                if (transportEvent.EventType == EventType.ReceivedPacket)
                {
                    AdtsLdapPacket packet = (AdtsLdapPacket)transportEvent.EventObject;
                    context = this.contextManager.GetContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);

                    return(packet);
                }
                else if (transportEvent.EventType == EventType.Disconnected)
                {
                    // Remove context if disconnected.
                    this.transportStack.Disconnect((IPEndPoint)transportEvent.EndPoint);
                    context = this.contextManager.GetContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);
                    this.contextManager.RemoveContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);

                    return(null);
                }
                else if (transportEvent.EventType == EventType.Exception)
                {
                    throw (Exception)transportEvent.EventObject;
                }
            }
        }
예제 #21
0
        /// <summary>
        /// Creates a SearchResultEntry packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="matchedDn">Matched DN.</param>
        /// <param name="attributes">The attributes and values that are contained in the entry.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultEntryPacket CreateSearchedResultEntry(
            AdtsLdapContext context,
            string matchedDn,
            params KeyValuePair <string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            PartialAttributeList_element[] partialAttributeElementArray = new PartialAttributeList_element[length];
            for (int i = 0; i < length; i++)
            {
                partialAttributeElementArray[i] = new PartialAttributeList_element(
                    new AttributeDescription(attributes[i].Key),
                    CreateAttributeValueSet(attributes[i].Value));
            }
            PartialAttributeList attributeList = new PartialAttributeList(partialAttributeElementArray);

            SearchResultEntry entry = new SearchResultEntry(
                new LDAPDN(matchedDn ?? string.Empty),
                attributeList);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.searchResEntry, entry);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultEntryPacket packet = new AdtsSearchResultEntryPacket();

            packet.ldapMessagev3 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
 /// <summary>
 /// Adds a context.
 /// </summary>
 /// <param name="context">The context to be added</param>
 /// <exception cref="ArgumentException">
 /// Thrown if the context exists already.
 /// </exception>
 internal void AddContext(AdtsLdapContext context, bool isTcp)
 {
     string key = GetKey(context.RemoteAddress, isTcp);
     lock (this.lockObject)
     {
         this.serverContexts.Add(key, context);
     }
 }
예제 #23
0
 /// <summary>
 /// Disconnects with specified client. The corresponding context will be removed.
 /// </summary>
 /// <param name="context">The context that contains the client information.</param>
 public void Disconnect(AdtsLdapContext context)
 {
     if (this.isTcp)
     {
         this.transportStack.Disconnect(context.RemoteAddress);
     }
     this.contextManager.RemoveContext(context.RemoteAddress, this.isTcp);
 }
        /// <summary>
        /// Adds a context.
        /// </summary>
        /// <param name="context">The context to be added</param>
        /// <exception cref="ArgumentException">
        /// Thrown if the context exists already.
        /// </exception>
        internal void AddContext(AdtsLdapContext context, bool isTcp)
        {
            string key = GetKey(context.RemoteAddress, isTcp);

            lock (this.lockObject)
            {
                this.serverContexts.Add(key, context);
            }
        }
 /// <summary>
 /// Creates a SearchResultDone packet.  For LDAP v3 only.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
 /// <param name="matchedDn">Matched DN.</param>
 /// <param name="errorMessage">Error message for result code. Required.</param>
 /// <param name="referral">Referral. Optional.</param>
 /// <returns>The packet that contains the response.</returns>
 internal override AdtsSearchResultDonePacket CreateSearchResultDone(
     AdtsLdapContext context,
     MsLdap.ResultCode resultCode,
     string matchedDn,
     string errorMessage,
     string[] referral)
 {
     throw new NotSupportedException();
 }
 /// <summary>
 /// Creates an ExtendedResponse packet. For LDAP v3 only.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
 /// <param name="matchedDn">Matched DN.</param>
 /// <param name="errorMessage">Error message for result code. Required.</param>
 /// <param name="referral">Referral. Optional. Used for LDAP v3 only.</param>
 /// <returns>The packet that contains the response.</returns>
 internal override AdtsExtendedResponsePacket CreateExtendedResponse(
     AdtsLdapContext context,
     MsLdap.ResultCode resultCode,
     string matchedDn,
     string errorMessage,
     string[] referral)
 {
     throw new NotSupportedException();
 }
예제 #27
0
 /// <summary>
 /// Creates a SearchRequest packet.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="dn">The DN to be searched.</param>
 /// <param name="sizeLimit">Size limit.</param>
 /// <param name="timeLimit">Time limit, in seconds.</param>
 /// <param name="scope">Search scope. Base, single level, or subtree.</param>
 /// <param name="dereferenceAliases">Dereference aliase options.</param>
 /// <param name="filter">Search filter.</param>
 /// <param name="typesOnly">
 /// Specifies whether the search returns only the attribute names without the attribute values.
 /// </param>
 /// <param name="attributes">The attributes to be retrieved.</param>
 /// <returns>The packet that contains the request.</returns>
 internal abstract AdtsSearchRequestPacket CreateSearchRequest(
     AdtsLdapContext context,
     string dn,
     long sizeLimit,
     long timeLimit,
     SearchScope scope,
     DereferenceAlias dereferenceAliases,
     Asn1Choice filter,
     bool typesOnly,
     params string[] attributes);
예제 #28
0
 public AdtsSearchResultReferencePacket CreateSearchResultReference(
     AdtsLdapContext context,
     string[] referenceUrls)
 {
     if (context.ServerVersion == AdtsLdapVersion.V2)
     {
         throw new NotSupportedException();
     }
     else
     {
         return(this.encoderv3.CreateSearchResultReference(context, referenceUrls));
     }
 }
예제 #29
0
        /// <summary>
        /// to receive bytes from connection.<para/>
        /// the transport must be TcpServer or NetbiosServer.
        /// </summary>
        /// <param name="timeout">
        /// a TimeSpan object that specifies the timeout for this operation.
        /// </param>
        /// <param name="maxCount">
        /// an int value that specifies the maximum count of expect bytes.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that indicates the connection to received data from.<para/>
        /// if Tcp, it's an IPEndPoint that specifies the target endpoint.<para/>
        /// if Netbios, it's an int value that specifies the client session id.
        /// </param>
        /// <returns>
        /// a bytes array that contains the received bytes.
        /// </returns>
        /// <exception cref="ObjectDisposedException">
        /// thrown when this object is disposed.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// thrown when maxCount is negative.
        /// </exception>
        public virtual byte[] ExpectBytes(TimeSpan timeout, int maxCount, AdtsLdapContext remoteEndPoint)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("TransportStack");
            }

            if (maxCount < 0)
            {
                throw new ArgumentException("max count must not be negative", "maxCount");
            }

            return(this.transportStack.ExpectBytes(timeout, maxCount, remoteEndPoint.RemoteAddress));
        }
예제 #30
0
        /// <summary>
        /// server authenticate over SSL/TLS with client.
        /// </summary>
        /// <param name="context">
        /// an AdtsLdapContext object that indicates the context of LDAP.
        /// </param>
        /// <param name="certificate">
        /// a X509Certificate that specifies the certificate used to authenticate the server.
        /// </param>
        /// <param name="encryptMessage">
        /// a bool value that indicates whether encrypt message.
        /// </param>
        /// <exception cref="ArgumentNullException">
        /// thrown when context is null.
        /// </exception>
        public void SslStartup(AdtsLdapContext context)
        {
            if (context == null)
            {
                throw new ArgumentNullException("context");
            }

            // if null or other security, initialize the ssl security.
            // when bind before start tls, the security will be set to other security.
            if (context.Security == null || !(context.Security is AdtsLdapSslTlsSecurityLayer))
            {
                context.Security = new AdtsLdapSslTlsSecurityLayer(this, context);
            }
        }
        /// <summary>
        /// Creates an AbandonRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="messageId">The ID of message to be abandoned.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAbandonRequestPacket CreateAbandonRequest(AdtsLdapContext context, long messageId)
        {
            AbandonRequest abandonRequest = new AbandonRequest(messageId);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.extendedReq, abandonRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsAbandonRequestPacket packet = new AdtsAbandonRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
예제 #32
0
 /// <summary>
 /// Creates a SearchResultEntry packet.
 /// </summary>
 /// <param name="context">The user context which contains message ID.</param>
 /// <param name="matchedDn">Matched DN.</param>
 /// <param name="attributes">The attributes and values that are contained in the entry.</param>
 /// <returns>The packet that contains the response.</returns>
 public AdtsSearchResultEntryPacket CreateSearchedResultEntry(
     AdtsLdapContext context,
     string matchedDn,
     params KeyValuePair <string, string[]>[] attributes)
 {
     if (context.ServerVersion == AdtsLdapVersion.V2)
     {
         return(this.encoderv2.CreateSearchedResultEntry(context, matchedDn, attributes));
     }
     else
     {
         return(this.encoderv3.CreateSearchedResultEntry(context, matchedDn, attributes));
     }
 }
        /// <summary>
        /// Creates a sicily response BindRequest packet. Usually it's the last packet of authentication during
        /// the bind process.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSicilyResponseBindRequest(
            AdtsLdapContext context,
            byte[] credential)
        {
            BindRequest_authentication authentication = new BindRequest_authentication();

            authentication.SetData(BindRequest_authentication.sicilyResponse, new Asn1OctetString(credential ?? (new byte[0])));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(string.Empty),
                authentication);

            return(CreateBindRequestPacket(context, bindRequest));
        }
        /// <summary>
        /// Creates an UnbindRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsUnbindRequestPacket CreateUnbindRequest(AdtsLdapContext context)
        {
            UnbindRequest unbindRequest = new UnbindRequest();

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.unbindRequest, unbindRequest);

            LDAPMessage             message = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsUnbindRequestPacket packet  = new AdtsUnbindRequestPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
        /// <summary>
        /// Creates an AbandonRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="messageId">The ID of message to be abandoned.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAbandonRequestPacket CreateAbandonRequest(AdtsLdapContext context, long messageId)
        {
            AbandonRequest abandonRequest = new AbandonRequest(messageId);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.abandonRequest, abandonRequest);

            LDAPMessage message             = new LDAPMessage(new MessageID(context.MessageId), operation);
            AdtsAbandonRequestPacket packet = new AdtsAbandonRequestPacket();

            packet.ldapMessagev2 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
        /// <summary>
        /// Creates a BindRequest with simple bind.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="name">
        /// The name field of BindRequest, see TD Section 5.1.1.1.1 for full list of legal names.
        /// </param>
        /// <param name="password">The password credential of the object.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSimpleBindRequest(
            AdtsLdapContext context,
            string name,
            string password)
        {
            BindRequest_authentication authentication = new BindRequest_authentication();

            authentication.SetData(BindRequest_authentication.simple, new Asn1OctetString(password ?? string.Empty));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(name ?? string.Empty),
                authentication);

            return(CreateBindRequestPacket(context, bindRequest));
        }
예제 #37
0
        /// <summary>
        /// Creates a DelRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be deleted.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsDelRequestPacket CreateDelRequest(AdtsLdapContext context, string objectDn)
        {
            DelRequest delRequest = new DelRequest(objectDn ?? string.Empty);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();

            operation.SetData(LDAPMessage_protocolOp.delRequest, delRequest);

            LDAPMessage          message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsDelRequestPacket packet  = new AdtsDelRequestPacket();

            packet.ldapMessagev3 = message;
            packet.messageId     = context.MessageId;

            return(packet);
        }
 /// <summary>
 /// Sends packet data to client (to keep compliant with Stack SDK conventions).
 /// </summary>
 /// <param name="context">The context that contains related info about client.</param>
 /// <param name="packetData">The packet data.</param>
 public void SendBytes(AdtsLdapContext context, byte[] packetData)
 {
     transportStack.SendBytes(context.RemoteAddress, packetData);
 }
        /// <summary>
        /// Creates a SicilyBindResponse packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="serverCredentials">Server credentials, optional for normal and sicily bind.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSicilyBindResponsePacket CreateSicilyBindResponse(
            AdtsLdapContext context,
            MsLdap.ResultCode resultCode,
            byte[] serverCredentials,
            string errorMessage)
        {
            SicilyBindResponse sicilyBindResponse = new SicilyBindResponse(
                new SicilyBindResponse_resultCode((long)resultCode),
                new Asn1OctetString(serverCredentials ?? (new byte[0])),
                new LDAPString(errorMessage ?? string.Empty));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.sicilybindResponse, sicilyBindResponse);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSicilyBindResponsePacket packet = new AdtsSicilyBindResponsePacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a SearchRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="dn">The DN to be searched.</param>
        /// <param name="sizeLimit">Size limit.</param>
        /// <param name="timeLimit">Time limit, in seconds.</param>
        /// <param name="scope">Search scope. Base, single level, or subtree.</param>
        /// <param name="dereferenceAliases">Dereference aliase options.</param>
        /// <param name="filter">Search filter.</param>
        /// <param name="typesOnly">
        /// Specifies whether the search returns only the attribute names without the attribute values.
        /// </param>
        /// <param name="attributes">The attributes to be retrieved.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsSearchRequestPacket CreateSearchRequest(
            AdtsLdapContext context,
            string dn,
            long sizeLimit,
            long timeLimit,
            MsLdap.SearchScope scope,
            MsLdap.DereferenceAlias dereferenceAliases,
            Asn1Choice filter,
            bool typesOnly,
            params string[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            AttributeDescription[] attributeDescriptionArray = new AttributeDescription[length];
            for (int i = 0; i < length; i++)
            {
                attributeDescriptionArray[i] = new AttributeDescription(attributes[i]);
            }
            AttributeDescriptionList attributeList = new AttributeDescriptionList(attributeDescriptionArray);

            SearchRequest searchRequest = new SearchRequest(
                new LDAPDN(dn ?? string.Empty),
                new SearchRequest_scope((long)scope),
                new SearchRequest_derefAliases((long)dereferenceAliases),
                new Asn1Integer(sizeLimit),
                new Asn1Integer(timeLimit),
                new Asn1Boolean(typesOnly),
                (Filter)filter,
                attributeList);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.searchRequest, searchRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchRequestPacket packet = new AdtsSearchRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a SearchResultDone packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="matchedDn">Matched DN.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <param name="referral">Referral. Optional.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultDonePacket CreateSearchResultDone(
            AdtsLdapContext context,
            MsLdap.ResultCode resultCode,
            string matchedDn,
            string errorMessage,
            string[] referral)
        {
            SearchResultDone searchResultDone = new SearchResultDone(
                new LDAPResult_resultCode((long)resultCode),
                new LDAPDN(matchedDn ?? string.Empty),
                new LDAPString(errorMessage ?? string.Empty),
                CreateReferral(referral));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.searchResDone, searchResultDone);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultDonePacket packet = new AdtsSearchResultDonePacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a BindRequest with SASL bind. This method is for LDAP v3 only.
        /// Note that for GSS-SPNEGO with NTLM, two rounds of bind requests is required.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="mechanism">Authentication mechanism used, e.g., GSS-SPNEGO, etc.</param>
        /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSaslBindRequest(
            AdtsLdapContext context,
            string mechanism,
            byte[] credential)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(
                AuthenticationChoice.sasl,
                new SaslCredentials(
                    new LDAPString(mechanism ?? string.Empty),
                    new Asn1OctetString(credential ?? (new byte[0]))));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),    // For SASL, DN is not required.
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a SearchResultEntry packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="matchedDn">Matched DN.</param>
        /// <param name="attributes">The attributes and values that are contained in the entry.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsSearchResultEntryPacket CreateSearchedResultEntry(
            AdtsLdapContext context,
            string matchedDn,
            params KeyValuePair<string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            PartialAttributeList_element[] partialAttributeElementArray = new PartialAttributeList_element[length];
            for (int i = 0; i < length; i++)
            {
                partialAttributeElementArray[i] = new PartialAttributeList_element(
                    new AttributeDescription(attributes[i].Key),
                    CreateAttributeValueSet(attributes[i].Value));
            }
            PartialAttributeList attributeList = new PartialAttributeList(partialAttributeElementArray);

            SearchResultEntry entry = new SearchResultEntry(
                new LDAPDN(matchedDn ?? string.Empty),
                attributeList);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.searchResEntry, entry);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsSearchResultEntryPacket packet = new AdtsSearchResultEntryPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a ModifyDNRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="oldDn">The original DN to be modified.</param>
        /// <param name="newRdn">The new relative DN.</param>
        /// <param name="newParentDn">
        /// The new parent DN. For LDAP v3 only. Ignored when creating LDAP v2 requests.
        /// </param>
        /// <param name="delOldRdn">
        /// Whether to delete old RDN. For LDAP v3 only. Ignored when creating LDAP v2 requests.
        /// </param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsModifyDnRequestPacket CreateModifyDnRequest(
            AdtsLdapContext context,
            string oldDn,
            string newRdn,
            string newParentDn,
            bool delOldRdn)
        {
            ModifyDNRequest modifyDnRequest = new ModifyDNRequest(
                new LDAPDN(oldDn ?? string.Empty),
                new RelativeLDAPDN(newRdn ?? string.Empty),
                new Asn1Boolean(delOldRdn),
                new LDAPDN(newParentDn ?? string.Empty));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.modDNRequest, modifyDnRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsModifyDnRequestPacket packet = new AdtsModifyDnRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// to receive bytes from connection.<para/>
        /// the transport must be TcpServer or NetbiosServer.
        /// </summary>
        /// <param name="timeout">
        /// a TimeSpan object that specifies the timeout for this operation.
        /// </param>
        /// <param name="maxCount">
        /// an int value that specifies the maximum count of expect bytes.
        /// </param>
        /// <param name="remoteEndPoint">
        /// an object that indicates the connection to received data from.<para/>
        /// if Tcp, it's an IPEndPoint that specifies the target endpoint.<para/>
        /// if Netbios, it's an int value that specifies the client session id.
        /// </param>
        /// <returns>
        /// a bytes array that contains the received bytes.
        /// </returns>
        /// <exception cref="ObjectDisposedException">
        /// thrown when this object is disposed.
        /// </exception>
        /// <exception cref="ArgumentException">
        /// thrown when maxCount is negative.
        /// </exception>
        public virtual byte[] ExpectBytes(TimeSpan timeout, int maxCount, AdtsLdapContext remoteEndPoint)
        {
            if (disposed)
            {
                throw new ObjectDisposedException("TransportStack");
            }

            if (maxCount < 0)
            {
                throw new ArgumentException("max count must not be negative", "maxCount");
            }

            return this.transportStack.ExpectBytes(timeout, maxCount, remoteEndPoint.RemoteAddress);
        }
        /// <summary>
        /// Decodes an LDAP v3 packet.
        /// </summary>
        /// <param name="messageBytes">The message bytes that contains the packet data.</param>
        /// <param name="context">The context that contains decode-related information.</param>
        /// <returns>Decoded LDAP v3 packet.</returns>
        internal override AdtsLdapPacket ParseAdtsLdapPacket(byte[] messageBytes, AdtsLdapContext context)
        {
            LDAPMessage message = new LDAPMessage();
            Asn1DecodingBuffer decodeBuffer = new Asn1DecodingBuffer(messageBytes);

            message.BerDecode(decodeBuffer);

            Type innerMessageType = message.protocolOp.GetData().GetType();
            AdtsLdapPacket packet = CreatePacketFromType(innerMessageType);

            context.MessageId = (long)message.messageID.Value;
            packet.messageId = (long)message.messageID.Value;
            packet.ldapMessagev3 = message;

            return packet;
        }
        /// <summary>
        /// Expects a packet.
        /// </summary>
        /// <param name="timeout">The timeout to be waited.</param>
        /// <param name="context">The context to be returned.</param>
        /// <returns>The packet received.</returns>
        public AdtsLdapPacket ExpectPacket(TimeSpan timeout, out AdtsLdapContext context)
        {
            while (true)
            {
                TransportEvent transportEvent = this.transportStack.ExpectTransportEvent(timeout);
                if (transportEvent.EventType == EventType.ReceivedPacket)
                {
                    AdtsLdapPacket packet = (AdtsLdapPacket)transportEvent.EventObject;
                    context = this.contextManager.GetContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);

                    return packet;
                }
                else if (transportEvent.EventType == EventType.Disconnected)
                {
                    // Remove context if disconnected.
                    this.transportStack.Disconnect((IPEndPoint)transportEvent.EndPoint);
                    context = this.contextManager.GetContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);
                    this.contextManager.RemoveContext((IPEndPoint)transportEvent.EndPoint, this.isTcp);

                    return null;
                }
                else if (transportEvent.EventType == EventType.Exception)
                {
                    throw (Exception)transportEvent.EventObject;
                }
            }
        }
        /// <summary>
        /// Creates a BindRequestPacket with context and BindRequest.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <param name="bindRequest">The BindRequest message.</param>
        /// <returns>The BindRequestPacket.</returns>
        private AdtsBindRequestPacket CreateBindRequestPacket(
            AdtsLdapContext context,
            BindRequest bindRequest)
        {
            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.bindRequest, bindRequest);

            MessageID messageId = new MessageID(context.MessageId);
            LDAPMessage message = new LDAPMessage(messageId, operation, null);

            AdtsBindRequestPacket packet = new AdtsBindRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a BindRequest with simple bind.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="name">
        /// The name field of BindRequest, see TD Section 5.1.1.1.1 for full list of legal names.
        /// </param>
        /// <param name="password">The password credential of the object.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSimpleBindRequest(
            AdtsLdapContext context,
            string name,
            string password)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.simple, new Asn1OctetString(password ?? string.Empty));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(name ?? string.Empty),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a sicily response BindRequest packet. Usually it's the last packet of authentication during
        /// the bind process.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="credential">The credential to be sent, it can be calculated with SSPI.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsBindRequestPacket CreateSicilyResponseBindRequest(
            AdtsLdapContext context,
            byte[] credential)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.sicilyResponse, new Asn1OctetString(credential ?? (new byte[0])));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
 /// <summary>
 /// Sends a packet.
 /// </summary>
 /// <param name="context">The context that contains related info about client.</param>
 /// <param name="packet">The packet to be sent.</param>
 public void SendPacket(AdtsLdapContext context, AdtsLdapPacket packet)
 {
     transportStack.SendPacket(context.RemoteAddress, packet);
 }
        /// <summary>
        /// Creates a ModifyRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of object to be modified.</param>
        /// <param name="modificationList">Modification list of attributes.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsModifyRequestPacket CreateModifyRequest(
            AdtsLdapContext context,
            string objectDn,
            params MsLdap.DirectoryAttributeModification[] modificationList)
        {
            int length = (modificationList != null) ? modificationList.Length : 0;

            ModifyRequest_modification_element[] modificationElements = new ModifyRequest_modification_element[length];
            for (int i = 0; i < length; i++)
            {
                byte[][] values = (byte[][])modificationList[i].GetValues(typeof(byte[]));

                modificationElements[i] = new ModifyRequest_modification_element(
                    new ModifyRequest_modification_element_operation((long)modificationList[i].Operation),
                    new AttributeTypeAndValues(
                        new AttributeDescription(modificationList[i].Name),
                        CreateAttributeValueSet(values)));
            }

            Asn1SequenceOf<ModifyRequest_modification_element> modificationSequence =
                new Asn1SequenceOf<ModifyRequest_modification_element>(modificationElements);

            ModifyRequest modifyRequest = new ModifyRequest(
                new LDAPDN(objectDn ?? string.Empty),
                modificationSequence);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.modifyRequest, modifyRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsModifyRequestPacket packet = new AdtsModifyRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a sicily package discovery BindRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <returns>The sicily package discovery BindRequest.</returns>
        internal override AdtsBindRequestPacket CreateSicilyPackageDiscoveryBindRequest(AdtsLdapContext context)
        {
            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.sicilyPackageDiscovery, new Asn1OctetString(string.Empty));

            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(new byte[0]),    // For Sicily package discovery, DN is not required.
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
 /// <summary>
 /// Disconnects with specified client. The corresponding context will be removed.
 /// </summary>
 /// <param name="context">The context that contains the client information.</param>
 public void Disconnect(AdtsLdapContext context)
 {
     if (this.isTcp)
     {
         this.transportStack.Disconnect(context.RemoteAddress);
     }
     this.contextManager.RemoveContext(context.RemoteAddress, this.isTcp);
 }
        /// <summary>
        /// Creates a BindRequest with simple bind for Active Directory Domain Services(AD DS).
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="username">User name which doesn't include domain prefix.</param>
        /// <param name="password">Password of user.</param>
        /// <param name="domainNetbiosName">NetBIOS domain name(with suffix like ".com" removed).</param>
        /// <returns>The packet that contains the request.</returns>
        /// <exception cref="ArgumentNullException">Thrown when username is null.</exception>
        internal override AdtsBindRequestPacket CreateSimpleBindRequest(
            AdtsLdapContext context,
            string username,
            string password,
            string domainNetbiosName)
        {
            if (username == null)
            {
                throw new ArgumentNullException("username");
            }

            AuthenticationChoice authentication = new AuthenticationChoice();
            authentication.SetData(AuthenticationChoice.simple, new Asn1OctetString(password ?? string.Empty));

            string fullname = (domainNetbiosName != null) ? (domainNetbiosName + "\\" + username) : username;
            BindRequest bindRequest = new BindRequest(
                new Asn1Integer((long)version),
                new LDAPDN(fullname),
                authentication);

            return CreateBindRequestPacket(context, bindRequest);
        }
        /// <summary>
        /// Creates a BindResponse for normal bindings, SASL bindings and sicily bindings.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="resultCode">Result code of previous request, as specified in RFC 2251.</param>
        /// <param name="matchedDn">Matched DN. Required, but can be an empty string.</param>
        /// <param name="errorMessage">Error message for result code. Required.</param>
        /// <param name="referral">Referral. Optional and for LDAP v3 only.</param>
        /// <param name="serverCredentials">Server credentials, optional for normal bind.</param>
        /// <returns>The packet that contains the response.</returns>
        internal override AdtsBindResponsePacket CreateBindResponse(
            AdtsLdapContext context,
            MsLdap.ResultCode resultCode,
            string matchedDn,
            string errorMessage,
            string[] referral,
            byte[] serverCredentials)
        {
            BindResponse bindResponse = new BindResponse(
                new LDAPResult_resultCode((long)resultCode),
                new LDAPDN(matchedDn ?? string.Empty),
                new LDAPString(errorMessage ?? string.Empty),
                CreateReferral(referral),
                new Asn1OctetString(serverCredentials ?? (new byte[0])));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.bindResponse, bindResponse);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsBindResponsePacket packet = new AdtsBindResponsePacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates an UnbindRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsUnbindRequestPacket CreateUnbindRequest(AdtsLdapContext context)
        {
            UnbindRequest unbindRequest = new UnbindRequest();

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.unbindRequest, unbindRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsUnbindRequestPacket packet = new AdtsUnbindRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a CompareRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be compared.</param>
        /// <param name="attributeName">The name of the attribute.</param>
        /// <param name="attributeValue">The value of the attribute.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsCompareRequestPacket CreateCompareRequest(
            AdtsLdapContext context,
            string objectDn,
            string attributeName,
            string attributeValue)
        {
            CompareRequest compareRequest = new CompareRequest(
                new LDAPDN(objectDn ?? string.Empty),
                new AttributeValueAssertion(
                    new AttributeDescription(attributeName ?? string.Empty),
                    new AssertionValue(attributeValue ?? string.Empty)));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.extendedReq, compareRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsCompareRequestPacket packet = new AdtsCompareRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates an AddRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be added.</param>
        /// <param name="attributes">Attributes to be set.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsAddRequestPacket CreateAddRequest(
            AdtsLdapContext context,
            string objectDn,
            params KeyValuePair<string, string[]>[] attributes)
        {
            int length = (attributes != null) ? attributes.Length : 0;

            AttributeList_element[] attributeArray = new AttributeList_element[length];
            for (int i = 0; i < length; i++)
            {
                AttributeValue[] attributeValues = new AttributeValue[attributes[i].Value.Length];
                for (int j = 0; j < attributes[i].Value.Length; i++)
                {
                    attributeValues[j] = new AttributeValue(attributes[i].Value[j]);
                }
                attributeArray[i] = new AttributeList_element(new AttributeDescription(attributes[i].Key), new Asn1SetOf<AttributeValue>(attributeValues));
            }

            AddRequest addRequest = new AddRequest(
                new LDAPDN(objectDn ?? string.Empty),
                new AttributeList(attributeArray));

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.extendedReq, addRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);

            AdtsAddRequestPacket packet = new AdtsAddRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }
        /// <summary>
        /// Creates a DelRequest packet.
        /// </summary>
        /// <param name="context">The user context which contains message ID.</param>
        /// <param name="objectDn">The DN of the object to be deleted.</param>
        /// <returns>The packet that contains the request.</returns>
        internal override AdtsDelRequestPacket CreateDelRequest(AdtsLdapContext context, string objectDn)
        {
            DelRequest delRequest = new DelRequest(objectDn ?? string.Empty);

            LDAPMessage_protocolOp operation = new LDAPMessage_protocolOp();
            operation.SetData(LDAPMessage_protocolOp.extendedReq, delRequest);

            LDAPMessage message = new LDAPMessage(new MessageID(context.MessageId), operation, null);
            AdtsDelRequestPacket packet = new AdtsDelRequestPacket();
            packet.ldapMessagev3 = message;
            packet.messageId = context.MessageId;

            return packet;
        }