238 lines
8.8 KiB
C#
238 lines
8.8 KiB
C#
using System;
|
|
using System.IO;
|
|
|
|
namespace Unosquare.Swan.Networking.Ldap {
|
|
/// <summary>
|
|
/// Encapsulates a single search result that is in response to an asynchronous
|
|
/// search operation.
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.LdapMessage" />
|
|
internal class LdapSearchResult : LdapMessage {
|
|
private LdapEntry _entry;
|
|
|
|
internal LdapSearchResult(RfcLdapMessage message)
|
|
: base(message) {
|
|
}
|
|
|
|
public LdapEntry Entry {
|
|
get {
|
|
if(this._entry != null) {
|
|
return this._entry;
|
|
}
|
|
|
|
LdapAttributeSet attrs = new LdapAttributeSet();
|
|
RfcSearchResultEntry entry = (RfcSearchResultEntry)this.Message.Response;
|
|
|
|
foreach(Asn1Object o in entry.Attributes.ToArray()) {
|
|
Asn1Sequence seq = (Asn1Sequence)o;
|
|
LdapAttribute attr = new LdapAttribute(((Asn1OctetString)seq.Get(0)).StringValue());
|
|
Asn1Set set = (Asn1Set)seq.Get(1);
|
|
|
|
foreach(Asn1Object t in set.ToArray()) {
|
|
attr.AddValue(((Asn1OctetString)t).ByteValue());
|
|
}
|
|
|
|
_ = attrs.Add(attr);
|
|
}
|
|
|
|
this._entry = new LdapEntry(entry.ObjectName, attrs);
|
|
|
|
return this._entry;
|
|
}
|
|
}
|
|
|
|
public override String ToString() => this._entry?.ToString() ?? base.ToString();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an Ldap Search Result Reference.
|
|
/// <pre>
|
|
/// SearchResultReference ::= [APPLICATION 19] SEQUENCE OF LdapURL
|
|
/// </pre>
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1SequenceOf" />
|
|
internal class RfcSearchResultReference : Asn1SequenceOf {
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RfcSearchResultReference"/> class.
|
|
/// The only time a client will create a SearchResultReference is when it is
|
|
/// decoding it from an Stream.
|
|
/// </summary>
|
|
/// <param name="stream">The streab.</param>
|
|
/// <param name="len">The length.</param>
|
|
public RfcSearchResultReference(Stream stream, Int32 len)
|
|
: base(stream, len) {
|
|
}
|
|
|
|
public override Asn1Identifier GetIdentifier() => new Asn1Identifier(LdapOperation.SearchResultReference);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an Ldap Extended Response.
|
|
/// <pre>
|
|
/// ExtendedResponse ::= [APPLICATION 24] SEQUENCE {
|
|
/// COMPONENTS OF LdapResult,
|
|
/// responseName [10] LdapOID OPTIONAL,
|
|
/// response [11] OCTET STRING OPTIONAL }
|
|
/// </pre>
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Sequence" />
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.IRfcResponse" />
|
|
internal class RfcExtendedResponse : Asn1Sequence, IRfcResponse {
|
|
public const Int32 ResponseNameCode = 10;
|
|
|
|
public const Int32 ResponseCode = 11;
|
|
|
|
private readonly Int32 _referralIndex;
|
|
private readonly Int32 _responseNameIndex;
|
|
private readonly Int32 _responseIndex;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RfcExtendedResponse"/> class.
|
|
/// The only time a client will create a ExtendedResponse is when it is
|
|
/// decoding it from an stream.
|
|
/// </summary>
|
|
/// <param name="stream">The stream.</param>
|
|
/// <param name="len">The length.</param>
|
|
public RfcExtendedResponse(Stream stream, Int32 len)
|
|
: base(stream, len) {
|
|
if(this.Size() <= 3) {
|
|
return;
|
|
}
|
|
|
|
for(Int32 i = 3; i < this.Size(); i++) {
|
|
Asn1Tagged obj = (Asn1Tagged)this.Get(i);
|
|
Asn1Identifier id = obj.GetIdentifier();
|
|
|
|
switch(id.Tag) {
|
|
case RfcLdapResult.Referral:
|
|
SByte[] content = ((Asn1OctetString)obj.TaggedValue).ByteValue();
|
|
|
|
using(MemoryStream bais = new MemoryStream(content.ToByteArray())) {
|
|
this.Set(i, new Asn1SequenceOf(bais, content.Length));
|
|
}
|
|
|
|
this._referralIndex = i;
|
|
break;
|
|
case ResponseNameCode:
|
|
this.Set(i, new Asn1OctetString(((Asn1OctetString)obj.TaggedValue).ByteValue()));
|
|
this._responseNameIndex = i;
|
|
break;
|
|
case ResponseCode:
|
|
this.Set(i, obj.TaggedValue);
|
|
this._responseIndex = i;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Asn1OctetString ResponseName => this._responseNameIndex != 0 ? (Asn1OctetString)this.Get(this._responseNameIndex) : null;
|
|
|
|
public Asn1OctetString Response => this._responseIndex != 0 ? (Asn1OctetString)this.Get(this._responseIndex) : null;
|
|
|
|
public Asn1Enumerated GetResultCode() => (Asn1Enumerated)this.Get(0);
|
|
|
|
public Asn1OctetString GetMatchedDN() => new Asn1OctetString(((Asn1OctetString)this.Get(1)).ByteValue());
|
|
|
|
public Asn1OctetString GetErrorMessage() => new Asn1OctetString(((Asn1OctetString)this.Get(2)).ByteValue());
|
|
|
|
public Asn1SequenceOf GetReferral()
|
|
=> this._referralIndex != 0 ? (Asn1SequenceOf)this.Get(this._referralIndex) : null;
|
|
|
|
public override Asn1Identifier GetIdentifier() => new Asn1Identifier(LdapOperation.ExtendedResponse);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents and Ldap Bind Response.
|
|
/// <pre>
|
|
/// BindResponse ::= [APPLICATION 1] SEQUENCE {
|
|
/// COMPONENTS OF LdapResult,
|
|
/// serverSaslCreds [7] OCTET STRING OPTIONAL }
|
|
/// </pre>
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Sequence" />
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.IRfcResponse" />
|
|
internal class RfcBindResponse : Asn1Sequence, IRfcResponse {
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RfcBindResponse"/> class.
|
|
/// The only time a client will create a BindResponse is when it is
|
|
/// decoding it from an InputStream
|
|
/// Note: If serverSaslCreds is included in the BindResponse, it does not
|
|
/// need to be decoded since it is already an OCTET STRING.
|
|
/// </summary>
|
|
/// <param name="stream">The in renamed.</param>
|
|
/// <param name="len">The length.</param>
|
|
public RfcBindResponse(Stream stream, Int32 len)
|
|
: base(stream, len) {
|
|
// Decode optional referral from Asn1OctetString to Referral.
|
|
if(this.Size() <= 3) {
|
|
return;
|
|
}
|
|
|
|
Asn1Tagged obj = (Asn1Tagged)this.Get(3);
|
|
|
|
if(obj.GetIdentifier().Tag != RfcLdapResult.Referral) {
|
|
return;
|
|
}
|
|
|
|
SByte[] content = ((Asn1OctetString)obj.TaggedValue).ByteValue();
|
|
|
|
using(MemoryStream bais = new MemoryStream(content.ToByteArray())) {
|
|
this.Set(3, new Asn1SequenceOf(bais, content.Length));
|
|
}
|
|
}
|
|
|
|
public Asn1Enumerated GetResultCode() => (Asn1Enumerated)this.Get(0);
|
|
|
|
public Asn1OctetString GetMatchedDN() => new Asn1OctetString(((Asn1OctetString)this.Get(1)).ByteValue());
|
|
|
|
public Asn1OctetString GetErrorMessage() => new Asn1OctetString(((Asn1OctetString)this.Get(2)).ByteValue());
|
|
|
|
public Asn1SequenceOf GetReferral() => this.Size() > 3 && this.Get(3) is Asn1SequenceOf ? (Asn1SequenceOf)this.Get(3) : null;
|
|
|
|
public override Asn1Identifier GetIdentifier() => new Asn1Identifier(LdapOperation.BindResponse);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an LDAP Intermediate Response.
|
|
/// IntermediateResponse ::= [APPLICATION 25] SEQUENCE {
|
|
/// COMPONENTS OF LDAPResult, note: only present on incorrectly
|
|
/// encoded response from pre Falcon-sp1 server
|
|
/// responseName [10] LDAPOID OPTIONAL,
|
|
/// responseValue [11] OCTET STRING OPTIONAL }.
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Sequence" />
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.IRfcResponse" />
|
|
internal class RfcIntermediateResponse : Asn1Sequence, IRfcResponse {
|
|
public const Int32 TagResponseName = 0;
|
|
public const Int32 TagResponse = 1;
|
|
|
|
public RfcIntermediateResponse(Stream stream, Int32 len)
|
|
: base(stream, len) {
|
|
Int32 i = this.Size() >= 3 ? 3 : 0;
|
|
|
|
for(; i < this.Size(); i++) {
|
|
Asn1Tagged obj = (Asn1Tagged)this.Get(i);
|
|
|
|
switch(obj.GetIdentifier().Tag) {
|
|
case TagResponseName:
|
|
this.Set(i, new Asn1OctetString(((Asn1OctetString)obj.TaggedValue).ByteValue()));
|
|
break;
|
|
case TagResponse:
|
|
this.Set(i, obj.TaggedValue);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
public Asn1Enumerated GetResultCode() => this.Size() > 3 ? (Asn1Enumerated)this.Get(0) : null;
|
|
|
|
public Asn1OctetString GetMatchedDN() => this.Size() > 3 ? new Asn1OctetString(((Asn1OctetString)this.Get(1)).ByteValue()) : null;
|
|
|
|
public Asn1OctetString GetErrorMessage() =>
|
|
this.Size() > 3 ? new Asn1OctetString(((Asn1OctetString)this.Get(2)).ByteValue()) : null;
|
|
|
|
public Asn1SequenceOf GetReferral() => this.Size() > 3 ? (Asn1SequenceOf)this.Get(3) : null;
|
|
|
|
public override Asn1Identifier GetIdentifier() => new Asn1Identifier(LdapOperation.IntermediateResponse);
|
|
}
|
|
} |