в Unix, поскольку стандартные вызовы



Подпрограммы для создания и удаления учетных записей в Windows NT/2000

Процесс создания и удаления учетных записей в Windows NT/2000 несколько проще, чем в Unix, поскольку стандартные вызовы API для этой операции существуют в NT. Как и в Unix, мы могли бы вызвать внешнюю программу, чтобы выполнить подобную работу (например, вездесущую команду net с ключом USERS/ADD), но проще использовать API-вызовы из многочисленных модулей, о некоторых из которых мы уже говорили. Функции для создания учетных записей есть, например, в Win32::NetAdmin, Win32: :UserAdmin, Win32API::Net и Win32::Lanman. Пользователям Windows 2000 лучше ознакомиться с материалом по ADSI в главе 6.

Выбор одного из этих модулей, в основном, дело вкуса. Чтобы разобраться в отличиях между ними, рассмотрим существующие вызовы для создания пользователей. Эти вызовы описаны в документации Network Management SDK на http://msdn.microsoft. com (если вы ничего не можете найти, поищите «NetUserAdd»). NetllserAdd() и другие вызовы принимают в качестве параметра информационный уровень данных. Например, если информационный уровень равен 1, структура данных на С, передаваемая вызову для создания пользователя, выглядит так:

typedef struct JJSER_INFO_1 {

LPWSTR usri1_name;

LPWSTR usri1_oassworc';

DWORD usril_passwora_age:

DWORD usril_oriv:

LPWSTR usril_home_dir;

LPWSTR usri1_comment;

DWORD usri1_flags:

LPWSTR usri1_script_pat!i:

}

Если используется информационный уровень, равный 2, структура значительно расширится:

typedef struct _UbER_INrG;



LPWSTR usn2_name;
LPWSTP lisri? password:
DWORD usri2_password_age:
DWORD usn2_priv:
LPWSTR Lisri2_home_dir;
LPWSTR usri2_conwient :
DWORD usri2_flags;
LPWSTR usri2_scnpt_path;
DWORD usri2_auth_f lags;
LPWSTR usri2_fiJll_name:
LPWSTR usri2_usr_comment;
LPWSTR usri2_parms:
LPWSTR usri2_workstations:
DWORD usri2_last_logon;
DWORD usn2_last_logoff ;
DWORD usri2_acct_expires;
DWORD usri2_max_storage;
DWORD usri2_units_per_week;
PBYTE usri2_logon_hours;
DWORD usri2_bad_pw^count;
DWORD usri2_num_logons;
LPWSTR usri2_logon_server;
DWORD usri2_country_code;
DWORD usri2_code_page;
He обязательно много знать об этих параметрах или даже вообще о С, чтобы понять, что при изменении уровня увеличивается количество информации, которое можно передать при создании пользователя. Кроме того, каждый последующий уровень является надмножеством предыдущего.

Какое это имеет отношение к Perl? Каждый упомянутый модуль требует принять два решения:

  1. Нужно ли объяснять программистам на Perl, что такое «информационный уровень»?
  2. Какой информационный уровень (т. е. сколько параметров) может использовать программист?
Модули Win32API: :Net и Win32: :UserAdmin позволяют программисту выбрать информационный уровень. Win32; : NetAdmin и Win32: : Lanrnan этого не делают. Из всех этих модулей Win32; :NetAdmin применяет наименьшее число параметров; в частности, вы не можете определить поле на этапе создания пользователя. Если вы решите применять модуль Win32; :NetAcmin, вам, скорее всего, придется дополнить его вызовами из другого модуля, чтобы установить те параметры, которые он устанавливать не позволяет. Если вы остановитесь на комбинации Win32 : : NetAarn.in и Win32 : : AaminMisc, вам стоит обратиться к многократно упомянутой книге Рота, поскольку это отличный справочник по модулю Win32: : NetAdmin, по которому нет достаточного количества документации.

Теперь читателю должно быть понятно, почему выбор модуля - это де ло личных предпочтений. Хорошей стратегией было бы сначала решить, какие параметры важны для вас, а затем найти модуль, который их поддерживает. Для наших демонстрационных подпрограмм мы выбираем модуль Win32: : Lanman. Вот какой код можно применить для создания и удаления пользователей в нашей системе учетных записей:

use Win32: :Lanman; tt для создания учетной записи

use Win32::Perms; # для установки прав на домашний каталог

$homeNTdirs = "\\\\homeserver\\home"; # корневой каталог

# домашних каталогов

sub CreateNTAccount{

my ($account,$record) = @_;

П создаем учетную запись на локальной машине

# (т. е., первый параметр пустой)

$result = Win32::Lanman::NetUserAdd("",

{'name' => Saccount,

'password' => $record->{password},

'home_dir' => "$homeNTdirs\\$account",

'full_name' => $record->{fullname}});

return Win32::Lanman::6etLastError() unless ($result);

добавляем в нужную ЛОКАЛЬНУЮ группу

(предварительно мы Я получаем SID учетной записи)

# Мы считаем, что имя группы совпадает с типом учетной

die "SID lookup error: ".Win32::Lanman::6etLastError()."\n"

unless (Win32: :Lanman: :LsalookupNames("", [$account],

\@info)); $result = Win32::Lanman::NetLocalGroupAddMember("",

$record->{type), ${$info[0]){sid»;

return Win32::Lanman::GetLastError() unless (Sresult);

# создаем домашний каталог

mkdir "$homeNTdirs\\$account",0777 or

return "Unable to make honedir:$!";

№ устанавливаем ACL и владельца каталога

$acl = new Win32::Perms("$homeNTdirs\\$account");

$acl->0wner($account);

# мы предоставляем пользователю полный контроль за

# каталогом и всеми файлами, которые будут в нем созданы

# (потому и два различных вызова)

DIRECTORY | СОНТШЕВ_ШЕИТ_АСЕ);

$acl->Allow($account, FULL, -

FILE|OBJECT_INHERIT_ACE|IMHERIT_ONLY_ACE);

$result = $acl->Set(); $acl->Close();

return($result ? "" : Sresult); }

Программа для удаления пользователей выглядит так:

use Win32: iLanman;

для удаления учетной записи

use File::Path;

для рекурсивного удаления каталогов

sub DeleteNTAccount{

my($account,$record) = @_;

# удаляем пользователя только из ЛОКАЛЬНЫХ групп.

Если мы № хотим удалить их и из глобальных групп, мы можем убрать

слово "Local" из двух вызовов Win32::Lanman::NetUser

(например, NetUserGetGroups)

die "SID lookup error: ".Win32::Lanman::GetLastError()."\n"

unless (Win32::Lanman::LsaLookupNames("",

[Saccount], \@info));

Win32::Lanman::NetUserGetLocalGroups($server, Saccount, ",

\@groups); foreach $group (@groups){

print "Removing user from local group ".

$group->{name}."...";

print(Win32::Lanman::NetLocalGroupDelMember("",

$group->{name}, ${$info[0]}{sid})?

"succeeded\n" : "FAILED\n"); }

tt удалить эту учетную запись с локальной машины

(т. е., перый параметр пустой) Sresult = Win32::Lanman::NetUserDel("", Saccount);

return Win32::Lanman::GetLastError() if ($result);

удалить домашний каталог и его содержимое

Sresult = rmtree("$homeNTdirs\\$account",0,1);

rmtree возвращает число удаленных файлов, так что если мы

удалили более нуля элементов, то скорее всего все прошло 8 успешно return Sresult;

}

Заметьте, для удаления домашнего каталога здесь используется переносимый модуль File: :Path. Если бы мы хотели сделать что-то специфичное для Win32, например, переместить домашний каталог в корзину, то могли бы сделать это при помощи модуля Win32: :File Op Йенды Крыники (Jenda Krynicky), который можно найти на http://jen da.krynicky.cz/. В таком случае мы применили бы Wi n32: ; F: 1еОр и изменили бы строку, включающую rmtrc-e(), на:

# удалим каталог в корзину, потенциально подтверждая

# действие пользователем, если для этой учетной записи

# необходимо подтверждать такие операции

$result = Recycle("$homeNTdirs\\$account");

В данном модуле есть функция Delete(), которая выполняет то же, что и rmtree() менее переносимым (правда, более быстрым) способом.

Содержание раздела