2016-02-12 3 views
3

У меня есть приложение Delphi, которое перезапускает определенную службу Windows.Олицетворять администратора для перезагрузки службы Windows

Если пользователь, выполняющий это приложение, имеет административные права (входит в группу «Администраторы»), перезапуск службы будет успешным.

Для обычного пользователя перезапуск службы завершился с ошибкой.

Это также будет успешным, если этот обычный пользователь использует «щелкните правой кнопкой мыши« Запуск от имени администратора ». Но обычный пользователь должен ввести имя пользователя и пароль администратора.

Я хочу решить это для обычного пользователя.

Моя идея - делать «олицетворять пользователя» в коде, явно выдавая себя за учетную запись локального администратора.

Но это все еще не работает.

Вот мой код:

function GetCurrUserName: string; 
var 
    Size    : DWORD; 
begin 
    Size := MAX_COMPUTERNAME_LENGTH + 1; 
    SetLength(Result, Size); 
    if GetUserName(PChar(Result), Size) then 
    SetLength(Result, Size) 
    else 
    Result := ''; 
end; 

function ConnectAs(const lpszUsername, lpszPassword: string): Boolean; 
var 
    hToken  : THandle; 
begin 
    Result := LogonUser(PChar(lpszUsername), nil, PChar(lpszPassword), LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, hToken); 
    if Result then 
    Result := ImpersonateLoggedOnUser(hToken) 
    else 
    RaiseLastOSError; 
end; 

И я называю это так:

try 
    ConnectAs('Administrator','password'); 
except 
    on E: Exception do 
    Writeln(E.ClassName, ': ', E.Message); 
end; 

// Restart the Windows service 

// Done, back to the user 
RevertToSelf; 

Перезапуск службы потерпит неудачу. Если пользователь запускает его как Администратор (щелкните правой кнопкой мыши RunAs), он работает.

Сам олицетворение работает отлично. Я мог бы проверить его с получением текущего имени пользователя. Но почему это все еще не работает. Похоже, что пользователь олицетворяет без прав администратора.

Есть ли другой вид олицетворения?

+1

Откуда вы получите местный пароль администратора? –

+0

Подтвержденный пользователем пароль не является секретным. И это не собственно учетная запись администратора, а другая учетная запись, входящая в группу «Администраторы». – ewlung

+3

Вы не проверяете возвращаемое значение 'ImpersonateLoggedOnUser'. Я не уверен, что можно будет подняться без прохождения UAC. Я бы предположил, что у вас есть две службы. Добавьте вторую службу охраны, которая может перезапустить первую службу. –

ответ

5

Этого можно ожидать. Под UAC пользователи в группе администраторов получают фильтрованный токен, если они не проходят через процесс повышения UAC. Вы выдаете себя за другого пользователя, но вы делаете это без повышения UAC и, следовательно, имеете фильтрованный, уменьшенный токен привилегий.

Чтобы выполнить код с повышенными правами, под UAC, вы должны пройти процесс выравнивания UAC. Если бы вы не могли этого сделать, UAC был бы бессмыслен.

Насколько я могу сказать, у вас есть следующие принципиальные возможности:

  1. запустить другой процесс, чтобы сделать работу, используя глагол runas оболочки, чтобы заставить высоту, или в самом деле какой-то другой механизм, чтобы организовать подъем. Это приведет к вашему диалогу UAC, которого вы хотите избежать.
  2. В качестве альтернативы можно установить две службы. Первая услуга - это служба, которую вы в настоящее время устанавливаете, та, которую вы хотите перезапустить. Вторая услуга - это небольшой и простой сервис, единственной задачей которого является выполнение этого перезапуска. Поскольку этот второй сервис запускается в сеансе 0, где нет UAC, вы можете легко организовать, что он имеет достаточные права для перезапуска первой службы. Когда вам нужно перезапустить службу 1 из своего приложения для настольных компьютеров, отправьте запрос на услугу 2, чтобы служба 2 могла выполнить перезапуск службы 1.

В качестве примечания, я не обращаю внимания, что вы не проверяете ошибки в вашем вызове ImpersonateLoggedOnUser.

+0

Спасибо, Дэвид. Я думаю, что теперь я понял, что касается этого ОАК. Вы правы, было бы бессмысленно, если его можно обойти, как это. Я попытаюсь реализовать вторую услугу. – ewlung