Как прочесть 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 шт):
Ох уж этот микрософт - угадай с трех раз как получить значение. После долгих размышлений и опыта в даной сфере - получилось. Привожу "черновой" рабочий вариант.
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.