118 lines
3.7 KiB
C#
118 lines
3.7 KiB
C#
using System;
|
|
namespace Unosquare.Swan.Networking.Ldap {
|
|
/// <summary>
|
|
/// Represents an Ldap Control.
|
|
/// <pre>
|
|
/// Control ::= SEQUENCE {
|
|
/// controlType LdapOID,
|
|
/// criticality BOOLEAN DEFAULT FALSE,
|
|
/// controlValue OCTET STRING OPTIONAL }
|
|
/// </pre>
|
|
/// </summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Sequence" />
|
|
internal class RfcControl : Asn1Sequence {
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="RfcControl"/> class.
|
|
/// Note: criticality is only added if true, as per RFC 2251 sec 5.1 part
|
|
/// (4): If a value of a type is its default value, it MUST be
|
|
/// absent.
|
|
/// </summary>
|
|
/// <param name="controlType">Type of the control.</param>
|
|
/// <param name="criticality">The criticality.</param>
|
|
/// <param name="controlValue">The control value.</param>
|
|
public RfcControl(String controlType, Asn1Boolean criticality = null, Asn1Object controlValue = null)
|
|
: base(3) {
|
|
this.Add(controlType);
|
|
this.Add(criticality ?? new Asn1Boolean(false));
|
|
|
|
if(controlValue != null) {
|
|
this.Add(controlValue);
|
|
}
|
|
}
|
|
|
|
public RfcControl(Asn1Structured seqObj)
|
|
: base(3) {
|
|
for(Int32 i = 0; i < seqObj.Size(); i++) {
|
|
this.Add(seqObj.Get(i));
|
|
}
|
|
}
|
|
|
|
public Asn1OctetString ControlType => (Asn1OctetString)this.Get(0);
|
|
|
|
public Asn1Boolean Criticality => this.Size() > 1 && this.Get(1) is Asn1Boolean boolean ? boolean : new Asn1Boolean(false);
|
|
|
|
public Asn1OctetString ControlValue {
|
|
get {
|
|
if(this.Size() > 2) {
|
|
// MUST be a control value
|
|
return (Asn1OctetString)this.Get(2);
|
|
}
|
|
|
|
return this.Size() > 1 && this.Get(1) is Asn1OctetString s ? s : null;
|
|
}
|
|
set {
|
|
if(value == null) {
|
|
return;
|
|
}
|
|
|
|
if(this.Size() == 3) {
|
|
// We already have a control value, replace it
|
|
this.Set(2, value);
|
|
return;
|
|
}
|
|
|
|
if(this.Size() == 2) {
|
|
// Get the second element
|
|
Asn1Object obj = this.Get(1);
|
|
|
|
// Is this a control value
|
|
if(obj is Asn1OctetString) {
|
|
// replace this one
|
|
this.Set(1, value);
|
|
} else {
|
|
// add a new one at the end
|
|
this.Add(value);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents Ldap Sasl Credentials.
|
|
/// <pre>
|
|
/// SaslCredentials ::= SEQUENCE {
|
|
/// mechanism LdapString,
|
|
/// credentials OCTET STRING OPTIONAL }
|
|
/// </pre></summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Sequence" />
|
|
internal class RfcSaslCredentials : Asn1Sequence {
|
|
public RfcSaslCredentials(String mechanism, SByte[] credentials = null)
|
|
: base(2) {
|
|
this.Add(mechanism);
|
|
if(credentials != null) {
|
|
this.Add(new Asn1OctetString(credentials));
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents an Ldap Authentication Choice.
|
|
/// <pre>
|
|
/// AuthenticationChoice ::= CHOICE {
|
|
/// simple [0] OCTET STRING,
|
|
/// -- 1 and 2 reserved
|
|
/// sasl [3] SaslCredentials }
|
|
/// </pre></summary>
|
|
/// <seealso cref="Unosquare.Swan.Networking.Ldap.Asn1Choice" />
|
|
internal class RfcAuthenticationChoice : Asn1Choice {
|
|
public RfcAuthenticationChoice(SByte[] passwd)
|
|
: base(new Asn1Tagged(new Asn1Identifier(0), new Asn1OctetString(passwd), false)) {
|
|
}
|
|
|
|
public RfcAuthenticationChoice(String mechanism, SByte[] credentials)
|
|
: base(new Asn1Tagged(new Asn1Identifier(3, true), new RfcSaslCredentials(mechanism, credentials), false)) {
|
|
// implicit tagging
|
|
}
|
|
}
|
|
} |