
Лабораторна робота №1. Функції управління користувачами в ос Windows. Теоретична частина
1. Додавання користувача
Для створення облікового запису користувача використовується функція NetuserAdd, яка має наступний прототип:
NET_API_STATUS NetUserAdd (
LPCWSTR servername, // ім’я сервера
DWORD level, // рівень інформації
LPBYTE buf, // вказівник на інформацію
LPDWORD parm_err // індексація структури з інформацією
);
Відмітимо, що успішно цю функцію можуть виконати тільки ті користувачі, які є адміністраторами або операторами облікових записів.
У випадку успішного завершення функція NetuserAdd повертає значення NERR_success, а у випадку невдачі можливі наступні коди завершення:
error_access_denied — користувачу відмовлено у доступі;
NERR_invaiidcomputer — неправильне ім’я комп’ютера;
NERR_NotPrimary — операція може виконуватися тільки на первинному контролері домену;
NERR_GroupExists — група вже існує;
NERR_userExists — обліковий запис вже існує;
NERR_PasswordTooShort — пароль коротший, ніж вимагається.
Параметри функції NetuserAdd мають наступне призначення.
Параметр servername повинен вказувати на рядок з іменем сервера, на якому буде виконуватися функція. Цей рядок повинен мати кодування Unicode і починається з символів \\. Якщо функція повинна виконуватися на локальному комп’ютері, то цей параметр повинен мати значення null.
Параметр level вказує тип структури, яка містить інформацію про користувача. Цей параметр може приймати одне з наступних значень:
1 — використовується структура типу user_info_i;
2 — використовується структура типу user_info_2;
3 — використовується структура типу user_info_3;
4 — використовується структура типу user_info_4.
В лістингу буде використана структура типу user_info_i, тому після опису функції приведемо тип і опишемо призначення полів цієї структури. Опис інших структур може боти знайдений в MSDN.
Параметр buf має вказувати на буфер з інформацією про користувача.
Інформація повинна зберігатися в структурі, тип якої задано параметром level.
В параметр parm_err функція NetuserAdd поміщає індекс першого поля в структурі з інформацією про користувача, яка містить неправильні дані і, як наслідок, викликало завершення функції NetuserAdd із помилкою. В цьому параметрі може бути встановлено значення null. В даному випадку індекс поля с неправильними даними не повертаються.
Тепер опишемо структуру user_info_i, яка використовуватиметься в лістингу. Ця структура має наступний тип:
typedef struct _USER_INFO_l {
LPWSTR usril_name; // ім’я користувача
lpwstr usril password; // пароль користувача
DWORD usril_password_age ; // вік пароля
DWORD usril_priv; // рівень прав
LPWSTR usril_home_dir; // домашний каталог
LPWSTR usril_comment; // коментарі
DWORD usril_flags; // прапорці
LPWSTR usril_script_path; // путь до скрипта
}USER_INFO_l, *PUSER_INFO_l, *LPUSER_INFO_l;
Поля цієї структури мають наступне призначення. У полі usrii_name зберігається покажчик на рядок з ім'ям користувача. Довжина рядка не повинна перевищувати unlen байтів, а сам рядок винен мати кодування Unicode. В полі usrii_password зберігається вказівник на рядок з паролем. Довжина рядка не повинна перевищувати pwlen байтів, а сам рядок повинен мати кодування Unicode.
Поле usrii_password_age призначене для зберігання кількості секунд які закінчилися з моменту останньої зміни пароля. Поле usrii_priv призначено для зберігання рівня прав, які отримує користувач. У цьому полі може зберігатися одне з наступних значень:
USER_PRIV_GUEST — ГОСТЬ;
user_priv_user — користувач;
user_priv_admin — адміністратор.
При виклику функції NetuserAdd це поле може містити тільки значення USER_PRIV_USER.
У полі usrii_home_dir зберігається покажчик на рядок з ім'ям домашнього каталогу користувача. Рядок повинен мати кодування Unicode. Це поле може містити значення null.
У полі usrii_coiranent зберігається покажчик на рядок з коментарями про користувача. Рядок повинен мати кодування Unicode. Це поле може містити значення null.
Поле usrii_fiags призначене для зберігання прапорів, що визначають тип облікового запису і її властивості. У цьому полі може бути встановлений один з наступних прапорів:
uf_normal_account — обліковий запис звичайного користувача;
uf_temp_duplicate_account — тимчасовий обліковий запис, дійсний тільки в домені;
uf_workstation_trust_account — обліковий запис комп'ютера в домені як робочої станції, так і сервера;
uf_server_trust_account — обліковий запис вторинного контролера домену;
uf_interdomain_trust_account — обліковий запис в довірчому домені.
Кроме того, в этом поле может быть установлена любая комбинация следующих флагов:
uf_script — исполнять скрипт (сценарий) при входе в систему;
uf_accountdisable — учетная запись недействительна;
uf_homedir_required — требуется домашний каталог;
uf_passwd_notreqd — пароль не требуется;
uf_passwd_cant_change — пароль нельзя изменять;
uf_lockout — учетная запись заблокирована;
uf_dont_expire_passwd — пароль не нужно изменять;
uf_encrypted_text_password_allowed — пароль збережений в зашифрованому вигляді в Active Directory;
uf_not_delegated — обліковий запис не може делегуватися іншим користувачам;
uf_smartcard_required — для входу в систему потрібна смарт-карта;
uf_use_des_key_only — використовувати тільки DES-стандарт шифрування;
uf_dont_require_preauth — не потрібна Kerberos-аутентифікація при вході в систему;
uf_trusted_for_delegation — обліковий запис може делегуватися;
uf_password_expired — час дії пароля закінчився.
Отметим, что, начиная с флага uf_dont_expire_passwd, все последующие флаги действительны только в версиях Windows 2000 и выше.
В поле usrii_script_path хранится указатель на строку с именем файла, содержащего скрипт, который выполняется перед входом пользователя в систему. Строка должна иметь кодировку Unicode. Это поле может содержать значение null.
В лістингу 1 приведена програма, яка створює обліковий запис користувача, використовуючи для цього функцію NetUserAdd.
Лістинг 1. Створення облікового запису користувача.
#include <stdio.h>
#include <windows.h>
#include <lm.h>
#pragma comment( lib, "netapi32.lib" ) // підключаємо мережеву бібліотеку
int main()
{
wchar_t server_name[256] = L"\\\\"; // ім’я сервера
wchar_t user_name[UNLEN]; // ім’я користувача
wchar_t user_password[PWLEN]; // пароль користувача
wchar_t user_comment[256]; // коментарі про користувача
USER_INFO_1 ui; // інформації про користувача
NET_API_STATUS ret_status; // код повернення з функції
printf("Input server name: ");
// формуємо ім’я сервера
wscanf(L"%s", server_name + wcslen(server_name));
printf("Input user name: "); // читаємо ім’я користувача
wscanf(L"%s", user_name); // читаємо ім’я користувача
ui.usri1_name = user_name; // встановлюємо ім’я користувача
printf("Input user password: ");
wscanf(L"%s", user_password); // читаємо пароль користувача
ui.usri1_password = user_password; // встановлюємо пароль користувача
ui.usri1_priv = USER_PRIV_USER; // звичайний користувач
ui.usri1_home_dir = NULL; // домашнього каталогу немає
printf("Input user comment: ");
getwchar(); // очищаємо потік
_getws(user_comment); // читаємо коментарі про користувача
ui.usri1_comment = user_comment; // встановлюємо коментарі
ui.usri1_flags = UF_SCRIPT; // виконувати скрипт при вході користувача в систему
ui.usri1_script_path = NULL; // поки файл із скриптом не визначений
// додаємо користувача
ret_status = NetUserAdd(
server_name, // ім’я сервера
1, // рівень інформації 1
(LPBYTE)&ui, // адреса інформації про користувача
NULL); // індексування в структурі даних відсутнє
// перевіряємо на успішне завершення
if (ret_status != NERR_Success)
{
printf("Net user add failed.\n");
printf("Error code: %u\n", ret_status);
return ret_status;
}
printf("The user is added.\n");
return 0;
}