Как защищенная строка направляется в неуправляемый код? - PullRequest
2 голосов
/ 02 октября 2009

Что вызвало этот вопрос: Я пытаюсь изменить учетную запись, под которой работает служба Windows. Я решил использовать Win32 API, а не WMI и начал смотреть на ChangeServiceConfig.

Я подумал, что могу просто использовать тип SecureString в сигнатуре неуправляемого метода, и он будет работать нормально. Хм, не совсем. Это заставило меня задуматься: кто-нибудь знает, какой собственный (win32) тип класса SecureString маршалируется как (по умолчанию) в неуправляемый код?

Ответы [ 4 ]

5 голосов
/ 01 декабря 2009

Я никогда не получал ответ на вопрос в заголовке, поэтому я до сих пор не знаю, что SecureString направляется в неуправляемый код.

Однако мой код заработал, используя рекомендации из некоторых других ответов. Я предоставил код ниже.

internal static class NativeService
{
    ...
    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    public static extern bool ChangeServiceConfig(IntPtr hService, uint nServiceType, uint nStartType, uint nErrorControl, string lpBinaryPathName, string lpLoadOrderGroup, IntPtr lpdwTagId, [In] char[] lpDependencies, string lpServiceStartName, IntPtr lpPassword, string lpDisplayName);
    ...
    public const uint SERVICE_NO_CHANGE = 0xffffffff;
}

internal class ClassThatConfiguresService
{
    ...
    public void ConfigureStartupAccount(IntPtr service, string userName, SecureString password)
    {
        passwordPointer = Marshal.SecureStringToGlobalAllocUnicode(password);
        try
        {
            if(!NativeService.ChangeServiceConfig(service, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, NativeService.SERVICE_NO_CHANGE, null, null, IntPtr.Zero, null, userName, passwordPointer, null))
                throw new Win32Exception(Marshal.GetLastWin32Error());
        }
        finally
        {
            Marshal.ZeroFreeGlobalAllocUnicode(passwordPointer);
        }
    }
    ...
}

Вместо Marshal.SecureStringToBSTR я использовал Marshal.SecureStringToGlobalAllocUnicode, потому что это то, что ожидает неуправляемая функция, но в остальном она обрабатывает удовольствие.

Надеюсь, кто-то еще найдет это полезным. Кеп.

4 голосов
/ 02 октября 2009

Похоже, вы можете использовать вспомогательные функции в пространстве имен InteropServices, чтобы помочь вам в этом:

Обратите внимание, что SecureString не имеет членов которые проверяют, сравнивают или преобразовывают значение SecureString. Отсутствие таких членов помогает защитить значение экземпляра из случайного или злонамеренное воздействие. Используйте соответствующие члены System.Runtime.InteropServices .. ::. Маршал класс, такой как SecureStringToBSTR метод, чтобы манипулировать значением SecureString объект.

Вы можете использовать SecureStringToBSTR , чтобы преобразовать строку в BSTR, а затем передать ее соответствующей функции для использования.

2 голосов
/ 02 октября 2009

Взгляните на метод MarshalSecureStringToBSTR .

0 голосов
/ 02 октября 2009

SecureString относится к типу non-blittable . Так что - нет win32 типа 1: 1.

Имейте в виду, что я вообще не эксперт COM.

...