Skip to main content

C# functions for generating octet strings from binary data such as GUIDs and SIDs; used in LDAP search/filter result retrieval.

using System.Text;

namespace Helpers
{
    internal static class StringHelper
    {
        /// <summary>
        /// Generates octet strings from binary data such as GUIDs and SIDs.
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        /// <example>
        /// The following example demonstrates SID Binding.
        /// <code>
        /// DirectoryEntry user = new DirectoryEntry(&quot;LDAP://CN=User1,CN=Users,DC=domain,DC=com&quot;, null, null, AuthenticationTypes.Secure);
        ///
        /// // Retrieve the SID
        /// byte[] sidBytes = user.Properties[&quot;objectSid&quot;].Value as byte[];
        ///
        /// // Format the bytes using the BuildOctetString function
        /// string adPath = String.Format(&quot;LDAP://&lt;SID={0}&gt;&quot;, BuildOctetString(sidBytes));
        ///
        /// DirectoryEntry sidBind = new DirectoryEntry(adPath, null, null, AuthenticationTypes.Secure);
        ///
        /// // Force the bind
        /// object native = sidBind.NativeObject;
        /// </code>
        /// </example>
        /// <remarks>
        /// Unlike the other special binding syntaxes, SID binding is available only over the LDAP port on Active Directory.
        /// Attempting to do a SID bind against the global catalog will result in an error.
        /// </remarks>
        public static string BuildOctetString(byte[] bytes)
        {
            var sb = new StringBuilder();

            for (int i = 0; i < bytes.Length; i++)
            {
                sb.Append(bytes[i].ToString("X2"));
            }

            return sb.ToString();
        }

        /// <summary>
        /// Converts binary data into the native LDAP Octet String format,
        /// especially designed for search filters.
        /// Search filters also use octet strings to specify binary data, but they must
        /// escape each byte with an additional "\" (back-slash) character in order to work.
        /// </summary>
        /// <param name="bytes"></param>
        /// <returns></returns>
        /// <example>
        /// How to convert a GUID to an LDAP Filter String.
        /// <code>
        /// Guid objectGuid = new Guid("4a5a0fa7-1200-4198-a3a7-31ee9ba10fc9");
        /// string filter = string.Format("(objectGUID={0})", BuildFilterOctetString(objectGuid.ToByteArray()));
        /// Console.WriteLine(filter);
        /// // OUT: (objectGUID=\A7\0F\5A\4A\00\12\98\41\A3\A7\31\EE\9B\A1\0F\C9)
        /// </code>
        /// We can easily apply this to any other type of binary data stored in the directory,
        /// including SIDs or even more esoteric data like JPEGs and X509 certificates, if we wish.
        /// </example>
        /// <remarks>Original: The .NET Developer's Guide to Directory Services Programming</remarks>
        public static string BuildFilterOctetString(byte[] bytes)
        {
            var sb = new StringBuilder();

            for (int i = 0; i < bytes.Length; i++)
            {
                sb.AppendFormat("\\{0}", bytes[i].ToString("X2"));
            }

            return sb.ToString();
        }
    }
}