etc/services - sync with NetBSD-8
[minix.git] / external / bsd / bind / dist / bin / win32 / BINDInstall / AccountInfo.cpp
blobc2baf0054c98e5640dc528bddb1d13ca3df073c6
1 /*
2 * Portions Copyright (C) 2004, 2007, 2009, 2013 Internet Systems Consortium, Inc. ("ISC")
3 * Portions Copyright (C) 2001, 2002 Internet Software Consortium.
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
9 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
10 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
11 * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
12 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
13 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
14 * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
15 * PERFORMANCE OF THIS SOFTWARE.
18 /* Id: AccountInfo.cpp,v 1.10 2009/09/29 23:48:04 tbox Exp */
20 /* Compiled with UNICODE */
22 #include "stdafx.h"
24 #include <windows.h>
25 #include <lm.h>
26 #include <ntsecapi.h>
28 #include <isc/ntgroups.h>
29 #include <isc/result.h>
30 #include "AccountInfo.h"
32 #define MAX_NAME_LENGTH 256
34 NTSTATUS
35 OpenPolicy(
36 LPWSTR ServerName, /* machine to open policy on (Unicode) */
37 DWORD DesiredAccess, /* desired access to policy */
38 PLSA_HANDLE PolicyHandle /* resultant policy handle */
41 BOOL
42 GetAccountSid(
43 LPTSTR SystemName, /* where to lookup account */
44 LPTSTR AccountName, /* account of interest */
45 PSID *Sid /* resultant buffer containing SID */
48 NTSTATUS
49 SetPrivilegeOnAccount(
50 LSA_HANDLE PolicyHandle, /* open policy handle */
51 PSID AccountSid, /* SID to grant privilege to */
52 LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
53 BOOL bEnable /* enable or disable */
56 NTSTATUS
57 GetPrivilegesOnAccount(
58 LSA_HANDLE PolicyHandle, /* open policy handle */
59 PSID AccountSid, /* SID to grant privilege to */
60 wchar_t **PrivList, /* Ptr to List of Privileges found */
61 unsigned int *PrivCount /* total number of Privileges in list */
64 NTSTATUS
65 AddPrivilegeToAcccount(
66 LPTSTR AccountName, /* Name of the account */
67 LPWSTR PrivilegeName /* Privilege to Add */
70 void
71 InitLsaString(
72 PLSA_UNICODE_STRING LsaString, /* destination */
73 LPWSTR String /* source (Unicode) */
76 void
77 DisplayNtStatus(
78 LPSTR szAPI, /* pointer to function name (ANSI) */
79 NTSTATUS Status /* NTSTATUS error value */
82 void
83 DisplayWinError(
84 LPSTR szAPI, /* pointer to function name (ANSI) */
85 DWORD WinError /* DWORD WinError */
88 #ifndef STATUS_SUCCESS
89 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
90 #endif
93 * Note that this code only retrieves the list of privileges of the
94 * requested account or group. However, all accounts belong to the
95 * Everyone group even though that group is not returned by the
96 * calls to get the groups to which that account belongs.
97 * The Everyone group has two privileges associated with it:
98 * SeChangeNotifyPrivilege and SeNetworkLogonRight
99 * It is not advisable to disable or remove these privileges
100 * from the group nor can the account be removed from the Everyone
101 * group
102 * The None group has no privileges associated with it and is the group
103 * to which an account belongs if it is associated with no group.
107 GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
108 char **Accounts, unsigned int *totalAccounts,
109 int maxAccounts)
111 LSA_HANDLE PolicyHandle;
112 TCHAR AccountName[256]; /* static account name buffer */
113 PSID pSid;
114 unsigned int i;
115 NTSTATUS Status;
116 isc_result_t istatus;
117 int iRetVal = RTN_ERROR; /* assume error from main */
120 * Open the policy on the target machine.
122 if ((Status = OpenPolicy(NULL,
123 POLICY_LOOKUP_NAMES,
124 &PolicyHandle)) != STATUS_SUCCESS)
125 return (RTN_ERROR);
128 * Let's see if the account exists. Return if not
130 wsprintf(AccountName, TEXT("%hS"), name);
131 if (!GetAccountSid(NULL, AccountName, &pSid))
132 return (RTN_NOACCOUNT);
134 * Find out what groups the account belongs to
136 istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
137 totalAccounts);
138 if (istatus == ISC_R_NOMEMORY)
139 return (RTN_NOMEMORY);
140 else if (istatus != ISC_R_SUCCESS)
141 return (RTN_ERROR);
143 Accounts[*totalAccounts] = name; /* Add the account to the list */
144 (*totalAccounts)++;
147 * Loop through each Account to get the list of privileges
149 for (i = 0; i < *totalAccounts; i++) {
150 wsprintf(AccountName, TEXT("%hS"), Accounts[i]);
151 /* Obtain the SID of the user/group. */
152 if (!GetAccountSid(NULL, AccountName, &pSid))
153 continue; /* Try the next one */
154 /* Get the Privileges allocated to this SID */
155 if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
156 PrivList, PrivCount)) == STATUS_SUCCESS)
158 iRetVal=RTN_OK;
159 if (pSid != NULL)
160 HeapFree(GetProcessHeap(), 0, pSid);
161 } else {
162 if (pSid != NULL)
163 HeapFree(GetProcessHeap(), 0, pSid);
164 continue; /* Try the next one */
168 * Close the policy handle.
170 LsaClose(PolicyHandle);
172 (*totalAccounts)--; /* Correct for the number of groups */
173 return iRetVal;
176 BOOL
177 CreateServiceAccount(char *name, char *password) {
178 NTSTATUS retstat;
179 USER_INFO_1 ui;
180 DWORD dwLevel = 1;
181 DWORD dwError = 0;
182 NET_API_STATUS nStatus;
184 size_t namelen = strlen(name);
185 size_t passwdlen = strlen(password);
186 wchar_t AccountName[MAX_NAME_LENGTH];
187 wchar_t AccountPassword[MAX_NAME_LENGTH];
189 mbstowcs(AccountName, name, namelen + 1);
190 mbstowcs(AccountPassword, password, passwdlen + 1);
193 * Set up the USER_INFO_1 structure.
194 * USER_PRIV_USER: name is required here when creating an account
195 * rather than an administrator or a guest.
198 ui.usri1_name = (LPWSTR) &AccountName;
199 ui.usri1_password = (LPWSTR) &AccountPassword;
200 ui.usri1_priv = USER_PRIV_USER;
201 ui.usri1_home_dir = NULL;
202 ui.usri1_comment = L"ISC BIND Service Account";
203 ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
204 UF_SCRIPT;
205 ui.usri1_script_path = NULL;
207 * Call the NetUserAdd function, specifying level 1.
209 nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
211 if (nStatus != NERR_Success)
212 return (FALSE);
214 retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
215 return (TRUE);
218 NTSTATUS
219 AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
220 LSA_HANDLE PolicyHandle;
221 TCHAR AccountName[256]; /* static account name buffer */
222 PSID pSid;
223 NTSTATUS Status;
224 unsigned long err;
227 * Open the policy on the target machine.
229 if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
230 != STATUS_SUCCESS)
231 return (RTN_ERROR);
234 * Let's see if the account exists. Return if not
236 wsprintf(AccountName, TEXT("%hS"), name);
237 if (!GetAccountSid(NULL, AccountName, &pSid))
238 return (RTN_NOACCOUNT);
240 err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
241 pSid, PrivilegeName, TRUE));
243 LsaClose(PolicyHandle);
244 if (err == ERROR_SUCCESS)
245 return (RTN_OK);
246 else
247 return (err);
250 void
251 InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
252 size_t StringLength;
254 if (String == NULL) {
255 LsaString->Buffer = NULL;
256 LsaString->Length = 0;
257 LsaString->MaximumLength = 0;
258 return;
261 StringLength = wcslen(String);
262 LsaString->Buffer = String;
263 LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
264 LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
267 NTSTATUS
268 OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
269 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
270 LSA_UNICODE_STRING ServerString;
271 PLSA_UNICODE_STRING Server = NULL;
274 * Always initialize the object attributes to all zeroes.
276 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
278 if (ServerName != NULL) {
280 * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
282 InitLsaString(&ServerString, ServerName);
283 Server = &ServerString;
287 * Attempt to open the policy.
289 return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
290 PolicyHandle));
293 BOOL
294 GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
295 LPTSTR ReferencedDomain = NULL;
296 DWORD cbSid = 128; /* initial allocation attempt */
297 DWORD cbReferencedDomain = 16; /* initial allocation size */
298 SID_NAME_USE peUse;
299 BOOL bSuccess = FALSE; /* assume this function will fail */
301 __try {
303 * initial memory allocations
305 if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
306 __leave;
308 if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
309 cbReferencedDomain)) == NULL) __leave;
312 * Obtain the SID of the specified account on the specified system.
314 while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
315 ReferencedDomain, &cbReferencedDomain,
316 &peUse))
318 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
319 /* reallocate memory */
320 if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
321 *Sid, cbSid)) == NULL) __leave;
323 if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
324 GetProcessHeap(), 0, ReferencedDomain,
325 cbReferencedDomain)) == NULL)
326 __leave;
328 else
329 __leave;
331 bSuccess = TRUE;
332 } /* finally */
333 __finally {
335 /* Cleanup and indicate failure, if appropriate. */
337 HeapFree(GetProcessHeap(), 0, ReferencedDomain);
339 if (!bSuccess) {
340 if (*Sid != NULL) {
341 HeapFree(GetProcessHeap(), 0, *Sid);
342 *Sid = NULL;
348 return (bSuccess);
351 NTSTATUS
352 SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
353 LPWSTR PrivilegeName, BOOL bEnable)
355 LSA_UNICODE_STRING PrivilegeString;
357 /* Create a LSA_UNICODE_STRING for the privilege name. */
358 InitLsaString(&PrivilegeString, PrivilegeName);
360 /* grant or revoke the privilege, accordingly */
361 if (bEnable)
362 return (LsaAddAccountRights(PolicyHandle, AccountSid,
363 &PrivilegeString, 1));
364 else
365 return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
366 FALSE, &PrivilegeString, 1));
369 NTSTATUS
370 GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
371 wchar_t **PrivList, unsigned int *PrivCount)
373 NTSTATUS Status;
374 LSA_UNICODE_STRING *UserRights;
375 ULONG CountOfRights;
376 unsigned int retlen = 0;
377 DWORD i, j;
378 int found;
380 Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
381 &UserRights, &CountOfRights);
382 /* Only continue if there is something */
383 if (UserRights == NULL || Status != STATUS_SUCCESS)
384 return (Status);
386 for (i = 0; i < CountOfRights; i++) {
387 found = -1;
388 retlen = UserRights[i].Length/sizeof(wchar_t);
389 for (j = 0; j < *PrivCount; j++) {
390 found = wcsncmp(PrivList[j], UserRights[i].Buffer,
391 retlen);
392 if (found == 0)
393 break;
395 if (found != 0) {
396 PrivList[*PrivCount] =
397 (wchar_t *)malloc(UserRights[i].MaximumLength);
398 if (PrivList[*PrivCount] == NULL)
399 return (RTN_NOMEMORY);
401 wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
402 retlen);
403 PrivList[*PrivCount][retlen] = L'\0';
404 (*PrivCount)++;
409 return (Status);
412 void
413 DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
414 /* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
415 DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
418 void
419 DisplayWinError(LPSTR szAPI, DWORD WinError) {
420 LPSTR MessageBuffer;
421 DWORD dwBufferLength;
423 if (dwBufferLength=FormatMessageA(
424 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
425 NULL, WinError, GetUserDefaultLangID(),
426 (LPSTR) &MessageBuffer, 0, NULL)){
427 DWORD dwBytesWritten; /* unused */
429 /* Output message string on stderr. */
430 WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
431 dwBufferLength, &dwBytesWritten, NULL);
433 /* Free the buffer allocated by the system. */
434 LocalFree(MessageBuffer);