/// <summary> /// Adds extended controls to a packet. /// </summary> /// <param name="packet">The packet to which the controls are added.</param> /// <param name="controls">The controls.</param> internal void AddDirectoryControls(AdtsLdapPacket packet, params MsLdap.DirectoryControl[] controls) { LDAPMessage message = packet.ldapMessagev3; int existingControlCount = (message.controls != null) ? message.controls.Elements.Length : 0; Control[] controlArray = new Control[existingControlCount + controls.Length]; // Add original existing controls for (int i = 0; i < existingControlCount; i++) { controlArray[i] = message.controls.Elements[i]; } // Add newly added controls for (int i = 0; i < controls.Length; i++) { controlArray[existingControlCount + i] = new Control( new LDAPOID(controls[i].Type), new Asn1Boolean(controls[i].IsCritical), new Asn1OctetString(controls[i].GetValue())); } Controls allControls = new Controls(controlArray); message.controls = allControls; }
/// <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> /// Adds extended controls to a packet. /// </summary> /// <param name="packet">The packet to which the controls are added.</param> /// <param name="controls">The controls.</param> /// <exception cref="NotSupportedException"> /// Thrown when trying to add controls to an LDAP v2 packet. /// </exception> public void AddDirectoryControls(AdtsLdapPacket packet, params DirectoryControl[] controls) { if (packet.ldapMessagev2 != null) { throw new NotSupportedException("Extended controls are only supported for LDAP v3 packets."); } this.encoderv3.AddDirectoryControls(packet, controls); }
/// <summary> /// Adds extended controls to a packet. /// </summary> /// <param name="packet">The packet to which the controls are added.</param> /// <param name="controls">The controls.</param> /// <exception cref="NotSupportedException"> /// Thrown when trying to add controls to an LDAP v2 packet. /// </exception> public virtual void AddDirectoryControls(AdtsLdapPacket packet, params DirectoryControl[] controls) { if (this.encoder is AdtsLdapV2Encoder) { throw new NotSupportedException("Extended controls are only supported for LDAP v3 packets."); } (this.encoder as AdtsLdapV3Encoder).AddDirectoryControls(packet, controls); }
/// <summary> /// Sends a packet to server. /// </summary> /// <param name="packet">The packet to be sent.</param> /// <exception cref="InvalidOperationException"> /// thrown when Transport is null! Please invoke Connect() first! /// </exception> public virtual void SendPacket(AdtsLdapPacket packet) { if (this.transportStack == null) { throw new InvalidOperationException("Transport is null! Please invoke Connect() first!"); } this.transportStack.SendPacket(packet); this.context.MessageId++; }
/// <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> /// This method encapsulates LdapV2Decoder and LdapV3Decoder because the incoming packets may be /// LDAP v2 or v3 packets, the decoding may require both decoders if the LDAP version that client uses /// is not clear. /// </summary> /// <param name="endPoint">The end point of the client.</param> /// <param name="messageBytes">The message bytes that contains the packet data.</param> /// <param name="consumedLength">Consumed length.</param> /// <param name="expectedLength"> /// Indicates expected length if the message bytes doesn't all packet data. /// </param> /// <returns>Decoded packets.</returns> internal override StackPacket[] DecodeLdapPacketCallBack( object endPoint, byte[] messageBytes, out int consumedLength, out int expectedLength) { // Get packet data, start decoding. IPEndPoint remote = (IPEndPoint)endPoint; AdtsLdapContext context = GetContext(remote, this.server.IsTcp); byte[] data = messageBytes; // decode messageBytes if needed if (context != null && messageBytes != null) { // if security is not init, and the package is SslHandshake, init security. if (context.Security == null) { AdtsLdapSslTlsSecurityHeader header = new AdtsLdapSslTlsSecurityHeader(); header.FromBytes(messageBytes); if (header.IsSslHandShake) { this.server.SslStartup(context); } } // decode messageBytes with security. if (context.Security != null) { data = this.server.Decrypt(context, messageBytes); } } byte[] packetData = this.GetSinglePacketData(data, out consumedLength, out expectedLength); // add the comsumed length of security decorder if (context != null && context.Security != null && context.Security.ConsumedData) { consumedLength = context.Security.ConsumedLength; } if (packetData == null) { return(null); } // New connection. Try both LDAP v2 and v3 decoders. Note that for requests that don't have version // context(e.g., UDP search requests), LDAP v3 is used by default. AdtsLdapPacket packet = null; if (context == null) { context = new AdtsLdapContext(AdtsLdapVersion.V3, remote); packet = this.decoderv3.ParseAdtsLdapPacket( this.decoderv3.AuthenticateMessage(packetData), context); // synchronize the message ID with newly received packet. context.MessageId = packet.messageId; // Check BindRequestPacket, normally it's the first message from client in which // contains the LDAP version. And since LDAP v3 decoder can decode LDAP v2 messages // without any exception, we need to check into the 'version' variable in the request. AdtsBindRequestPacket bindRequestPacket = packet as AdtsBindRequestPacket; if (bindRequestPacket != null) { LdapV3.BindRequest bindRequest = (LdapV3.BindRequest)bindRequestPacket.GetInnerRequestOrResponse(); // Version doesn't match. Decode again with LDAP v2 decoder and update context version. if ((AdtsLdapVersion)bindRequest.version.Value == AdtsLdapVersion.V2) { packet = this.decoderv2.ParseAdtsLdapPacket( this.decoderv2.AuthenticateMessage(packetData), context); context.ClientVersion = context.ServerVersion = AdtsLdapVersion.V2; } } // Add context. this.server.ContextManager.AddContext(context, this.server.IsTcp); } else { if (context.ClientVersion == AdtsLdapVersion.V2) { packet = this.decoderv2.ParseAdtsLdapPacket( this.decoderv2.AuthenticateMessage(packetData), context); } else { packet = this.decoderv3.ParseAdtsLdapPacket( this.decoderv3.AuthenticateMessage(packetData), context); } // synchronize the message ID with newly received packet. context.MessageId = packet.messageId; } return(new StackPacket[] { packet }); }
/// <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); }
internal AdtsLdapPacket CreatePacketFromType(Type messageType) { AdtsLdapPacket packet = null; if (messageType == typeof(AbandonRequest)) { packet = new AdtsAbandonRequestPacket(); } else if (messageType == typeof(AddRequest)) { packet = new AdtsAddRequestPacket(); } else if (messageType == typeof(AddResponse)) { packet = new AdtsAddResponsePacket(); } else if (messageType == typeof(BindRequest)) { packet = new AdtsBindRequestPacket(); } else if (messageType == typeof(BindResponse)) { packet = new AdtsBindResponsePacket(); } else if (messageType == typeof(CompareRequest)) { packet = new AdtsCompareRequestPacket(); } else if (messageType == typeof(CompareResponse)) { packet = new AdtsCompareResponsePacket(); } else if (messageType == typeof(DelRequest)) { packet = new AdtsDelRequestPacket(); } else if (messageType == typeof(DelResponse)) { packet = new AdtsDelResponsePacket(); } else if (messageType == typeof(ExtendedRequest)) { packet = new AdtsExtendedRequestPacket(); } else if (messageType == typeof(ExtendedResponse)) { packet = new AdtsExtendedResponsePacket(); } else if (messageType == typeof(ModifyDNRequest)) { packet = new AdtsModifyDnRequestPacket(); } else if (messageType == typeof(ModifyDNResponse)) { packet = new AdtsModifyDnResponsePacket(); } else if (messageType == typeof(ModifyRequest)) { packet = new AdtsModifyRequestPacket(); } else if (messageType == typeof(ModifyResponse)) { packet = new AdtsModifyResponsePacket(); } else if (messageType == typeof(SearchRequest)) { packet = new AdtsSearchRequestPacket(); } else if (messageType == typeof(SearchResultEntry)) { packet = new AdtsSearchResultEntryPacket(); } else if (messageType == typeof(SearchResultReference)) { packet = new AdtsSearchResultReferencePacket(); } else if (messageType == typeof(SearchResultDone)) { packet = new AdtsSearchResultDonePacket(); } else if (messageType == typeof(SicilyBindResponse)) { packet = new AdtsSicilyBindResponsePacket(); } else if (messageType == typeof(UnbindRequest)) { packet = new AdtsUnbindRequestPacket(); } else { throw new StackException("Unknown message type: " + messageType.ToString()); } return(packet); }