Как прочесть orname LDAP

Читал что о том, что в msPKIAccountCredentials хранятся хеши паролей, при попытке прочесть ключ - получаю __ComObject который не удаётся ни во что преобразовать. AdExplorer показывает что тип данных "ORName" и данные похоже что в "двоичном" виде. Как средствами c# прочесть это свойство? Это не единственное свойство которое имеет такой "тип данных".

public static void Main(string[] args){
  System.DirectoryServices.DirectoryEntry d = new  System.DirectoryServices.DirectoryEntry("LDAP://мой_лдап.loc", "логин", "пароль");
  System.DirectoryServices.DirectorySearcher ds = 
  new System.DirectoryServices.DirectorySearcher(d, "(&(objectCategory=user)(mail=мой_емайл))");
   if (ds.FindOne() != null) {
   object x = ds.FindOne().GetDirectoryEntry().Properties["msPKIAccountCredentials"].Value;
   object[] xx = (object[])x;
   Type t = xx[0].GetType();
   Console.WriteLine(xx[0].ToString());
   // И всё.
  }
}

Ответ получаю __ComObject и не удаётся никак вычитать что там за значения. "Тип данных" или схема похоже тут http://docs.microsoft.com/en-us/windows/win32/adschema/s-object-or-name описана.


Ответы (1 шт):

Автор решения: nick_n_a

Ох уж этот микрософт - угадай с трех раз как получить значение. После долгих размышлений и опыта в даной сфере - получилось. Привожу "черновой" рабочий вариант.

public static void Main(string[] args){
  System.DirectoryServices.DirectoryEntry d = new  System.DirectoryServices.DirectoryEntry("LDAP://мой_лдап.loc", "логин", "пароль");
  System.DirectoryServices.DirectorySearcher ds = 
  new System.DirectoryServices.DirectorySearcher(d, "(&(objectCategory=user)(mail=мой_емайл))");
   if (ds.FindOne() != null) {
   object x = ds.FindOne().GetDirectoryEntry().Properties["msPKIAccountCredentials"].Value;
   object[] xx = (object[])x;
   object v = null;
   ((IADsDNWithBinary)xx[0]).get_BinaryValue(out v);//TODO:Элементов не 1, а xx.Length,доработать
   if (v != null) {
      byte[] b = (byte[])v; // TODO: проверить тип v;
     foreach(byte bb in b) Console.Write(bb+ " ");
     }
   }// Конец main

// Вспомагательный класс
[Guid("7E99C0A2-F935-11D2-BA96-00C04FB6D0D1"),ComImport(),InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
interface IADsDNWithBinary{
[PreserveSig]int GetTypeInfoCount(out int pctinfo);
[PreserveSig]int GetTypeInfo([MarshalAs(UnmanagedType.U4)] int iTInfo,[MarshalAs(UnmanagedType.U4)] int lcid,out System.Runtime.InteropServices.ComTypes.ITypeInfo ppTInfo);
[PreserveSig]int GetIDsOfNames(ref Guid riid,[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.LPWStr)] string[] rgszNames,int cNames,int lcid, [MarshalAs(UnmanagedType.LPArray)] int[] rgDispId);
[PreserveSig]int Invoke(int dispIdMember,ref Guid riid,uint lcid,  ushort wFlags,ref System.Runtime.InteropServices.ComTypes.DISPPARAMS pDispParams,out object pVarResult,ref System.Runtime.InteropServices.ComTypes.EXCEPINFO pExcepInfo,IntPtr[] puArgErr); 
// Начало IADsDNWithBinary
[PreserveSig]   int get_BinaryValue(out object retVal);
[PreserveSig]   int put_BinaryValue(object value);
// Тут ещё есть два метода, смотреть iads.h
}

P.S. __ComObject должен автоматически уметь конвертироваться в нужный класс, но для этого возможно нужно подключить какую-то сборку (и надо точно знать какую), если она конечно существует. Но пока что не нашёл как проще решить эту проблему, если найдёте - пишите - приму ответ который получше.

Так же похожим образом решаются проблемы с отображением других "syntaxes": DN-Binary DN-String OR-Name NT-Sec-Desc.

→ Ссылка