RaspberryIO/Unosquare.Swan/Networking/Ldap/RfcControl.cs
2019-12-03 18:44:25 +01:00

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
}
}
}