No empty .Rs/.Re
[netbsd-mini2440.git] / external / bsd / bind / dist / bin / win32 / BINDInstall / AccountInfo.cpp
blob30c49d088973f48a3e783ed54f551641bd845faa
1 /*
2 * Portions Copyright (C) 2004, 2007, 2009 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 #ifndef UNICODE
21 #define UNICODE
22 #endif /* UNICODE */
24 #include "stdafx.h"
26 #include <windows.h>
27 #include <lm.h>
28 #include <ntsecapi.h>
30 #include <isc/ntgroups.h>
31 #include <isc/result.h>
32 #include "AccountInfo.h"
34 #define MAX_NAME_LENGTH 256
36 NTSTATUS
37 OpenPolicy(
38 LPWSTR ServerName, /* machine to open policy on (Unicode) */
39 DWORD DesiredAccess, /* desired access to policy */
40 PLSA_HANDLE PolicyHandle /* resultant policy handle */
43 BOOL
44 GetAccountSid(
45 LPTSTR SystemName, /* where to lookup account */
46 LPTSTR AccountName, /* account of interest */
47 PSID *Sid /* resultant buffer containing SID */
50 NTSTATUS
51 SetPrivilegeOnAccount(
52 LSA_HANDLE PolicyHandle, /* open policy handle */
53 PSID AccountSid, /* SID to grant privilege to */
54 LPWSTR PrivilegeName, /* privilege to grant (Unicode) */
55 BOOL bEnable /* enable or disable */
58 NTSTATUS
59 GetPrivilegesOnAccount(
60 LSA_HANDLE PolicyHandle, /* open policy handle */
61 PSID AccountSid, /* SID to grant privilege to */
62 wchar_t **PrivList, /* Ptr to List of Privileges found */
63 unsigned int *PrivCount /* total number of Privileges in list */
66 NTSTATUS
67 AddPrivilegeToAcccount(
68 LPTSTR AccountName, /* Name of the account */
69 LPWSTR PrivilegeName /* Privilege to Add */
72 void
73 InitLsaString(
74 PLSA_UNICODE_STRING LsaString, /* destination */
75 LPWSTR String /* source (Unicode) */
78 void
79 DisplayNtStatus(
80 LPSTR szAPI, /* pointer to function name (ANSI) */
81 NTSTATUS Status /* NTSTATUS error value */
84 void
85 DisplayWinError(
86 LPSTR szAPI, /* pointer to function name (ANSI) */
87 DWORD WinError /* DWORD WinError */
90 #ifndef STATUS_SUCCESS
91 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
92 #endif
95 * Note that this code only retrieves the list of privileges of the
96 * requested account or group. However, all accounts belong to the
97 * Everyone group even though that group is not returned by the
98 * calls to get the groups to which that account belongs.
99 * The Everyone group has two privileges associated with it:
100 * SeChangeNotifyPrivilege and SeNetworkLogonRight
101 * It is not advisable to disable or remove these privileges
102 * from the group nor can the account be removed from the Everyone
103 * group
104 * The None group has no privileges associated with it and is the group
105 * to which an account belongs if it is associated with no group.
109 GetAccountPrivileges(char *name, wchar_t **PrivList, unsigned int *PrivCount,
110 char **Accounts, unsigned int *totalAccounts,
111 int maxAccounts)
113 LSA_HANDLE PolicyHandle;
114 TCHAR AccountName[256]; /* static account name buffer */
115 PSID pSid;
116 unsigned int i;
117 NTSTATUS Status;
118 isc_result_t istatus;
119 int iRetVal = RTN_ERROR; /* assume error from main */
122 * Open the policy on the target machine.
124 if ((Status = OpenPolicy(NULL,
125 POLICY_LOOKUP_NAMES,
126 &PolicyHandle)) != STATUS_SUCCESS)
127 return (RTN_ERROR);
130 * Let's see if the account exists. Return if not
132 wsprintf(AccountName, TEXT("%hS"), name);
133 if (!GetAccountSid(NULL, AccountName, &pSid))
134 return (RTN_NOACCOUNT);
136 * Find out what groups the account belongs to
138 istatus = isc_ntsecurity_getaccountgroups(name, Accounts, maxAccounts,
139 totalAccounts);
140 if (istatus == ISC_R_NOMEMORY)
141 return (RTN_NOMEMORY);
142 else if (istatus != ISC_R_SUCCESS)
143 return (RTN_ERROR);
145 Accounts[*totalAccounts] = name; /* Add the account to the list */
146 (*totalAccounts)++;
149 * Loop through each Account to get the list of privileges
151 for (i = 0; i < *totalAccounts; i++) {
152 wsprintf(AccountName, TEXT("%hS"), Accounts[i]);
153 /* Obtain the SID of the user/group. */
154 if (!GetAccountSid(NULL, AccountName, &pSid))
155 continue; /* Try the next one */
156 /* Get the Privileges allocated to this SID */
157 if ((Status = GetPrivilegesOnAccount(PolicyHandle, pSid,
158 PrivList, PrivCount)) == STATUS_SUCCESS)
160 iRetVal=RTN_OK;
161 if (pSid != NULL)
162 HeapFree(GetProcessHeap(), 0, pSid);
163 } else {
164 if (pSid != NULL)
165 HeapFree(GetProcessHeap(), 0, pSid);
166 continue; /* Try the next one */
170 * Close the policy handle.
172 LsaClose(PolicyHandle);
174 (*totalAccounts)--; /* Correct for the number of groups */
175 return iRetVal;
178 BOOL
179 CreateServiceAccount(char *name, char *password) {
180 NTSTATUS retstat;
181 USER_INFO_1 ui;
182 DWORD dwLevel = 1;
183 DWORD dwError = 0;
184 NET_API_STATUS nStatus;
186 size_t namelen = strlen(name);
187 size_t passwdlen = strlen(password);
188 wchar_t AccountName[MAX_NAME_LENGTH];
189 wchar_t AccountPassword[MAX_NAME_LENGTH];
191 mbstowcs(AccountName, name, namelen + 1);
192 mbstowcs(AccountPassword, password, passwdlen + 1);
195 * Set up the USER_INFO_1 structure.
196 * USER_PRIV_USER: name is required here when creating an account
197 * rather than an administrator or a guest.
200 ui.usri1_name = (LPWSTR) &AccountName;
201 ui.usri1_password = (LPWSTR) &AccountPassword;
202 ui.usri1_priv = USER_PRIV_USER;
203 ui.usri1_home_dir = NULL;
204 ui.usri1_comment = L"ISC BIND Service Account";
205 ui.usri1_flags = UF_PASSWD_CANT_CHANGE | UF_DONT_EXPIRE_PASSWD |
206 UF_SCRIPT;
207 ui.usri1_script_path = NULL;
209 * Call the NetUserAdd function, specifying level 1.
211 nStatus = NetUserAdd(NULL, dwLevel, (LPBYTE)&ui, &dwError);
213 if (nStatus != NERR_Success)
214 return (FALSE);
216 retstat = AddPrivilegeToAcccount(name, SE_SERVICE_LOGON_PRIV);
217 return (TRUE);
220 NTSTATUS
221 AddPrivilegeToAcccount(LPTSTR name, LPWSTR PrivilegeName) {
222 LSA_HANDLE PolicyHandle;
223 TCHAR AccountName[256]; /* static account name buffer */
224 PSID pSid;
225 NTSTATUS Status;
226 unsigned long err;
229 * Open the policy on the target machine.
231 if ((Status = OpenPolicy(NULL, POLICY_ALL_ACCESS, &PolicyHandle))
232 != STATUS_SUCCESS)
233 return (RTN_ERROR);
236 * Let's see if the account exists. Return if not
238 wsprintf(AccountName, TEXT("%hS"), name);
239 if (!GetAccountSid(NULL, AccountName, &pSid))
240 return (RTN_NOACCOUNT);
242 err = LsaNtStatusToWinError(SetPrivilegeOnAccount(PolicyHandle,
243 pSid, PrivilegeName, TRUE));
245 LsaClose(PolicyHandle);
246 if (err == ERROR_SUCCESS)
247 return (RTN_OK);
248 else
249 return (err);
252 void
253 InitLsaString(PLSA_UNICODE_STRING LsaString, LPWSTR String){
254 size_t StringLength;
256 if (String == NULL) {
257 LsaString->Buffer = NULL;
258 LsaString->Length = 0;
259 LsaString->MaximumLength = 0;
260 return;
263 StringLength = wcslen(String);
264 LsaString->Buffer = String;
265 LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
266 LsaString->MaximumLength = (USHORT)(StringLength+1) * sizeof(WCHAR);
269 NTSTATUS
270 OpenPolicy(LPWSTR ServerName, DWORD DesiredAccess, PLSA_HANDLE PolicyHandle){
271 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
272 LSA_UNICODE_STRING ServerString;
273 PLSA_UNICODE_STRING Server = NULL;
276 * Always initialize the object attributes to all zeroes.
278 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
280 if (ServerName != NULL) {
282 * Make a LSA_UNICODE_STRING out of the LPWSTR passed in
284 InitLsaString(&ServerString, ServerName);
285 Server = &ServerString;
289 * Attempt to open the policy.
291 return (LsaOpenPolicy(Server, &ObjectAttributes, DesiredAccess,
292 PolicyHandle));
295 BOOL
296 GetAccountSid(LPTSTR SystemName, LPTSTR AccountName, PSID *Sid) {
297 LPTSTR ReferencedDomain = NULL;
298 DWORD cbSid = 128; /* initial allocation attempt */
299 DWORD cbReferencedDomain = 16; /* initial allocation size */
300 SID_NAME_USE peUse;
301 BOOL bSuccess = FALSE; /* assume this function will fail */
303 __try {
305 * initial memory allocations
307 if ((*Sid = HeapAlloc(GetProcessHeap(), 0, cbSid)) == NULL)
308 __leave;
310 if ((ReferencedDomain = (LPTSTR) HeapAlloc(GetProcessHeap(), 0,
311 cbReferencedDomain)) == NULL) __leave;
314 * Obtain the SID of the specified account on the specified system.
316 while (!LookupAccountName(SystemName, AccountName, *Sid, &cbSid,
317 ReferencedDomain, &cbReferencedDomain,
318 &peUse))
320 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
321 /* reallocate memory */
322 if ((*Sid = HeapReAlloc(GetProcessHeap(), 0,
323 *Sid, cbSid)) == NULL) __leave;
325 if ((ReferencedDomain= (LPTSTR) HeapReAlloc(
326 GetProcessHeap(), 0, ReferencedDomain,
327 cbReferencedDomain)) == NULL)
328 __leave;
330 else
331 __leave;
333 bSuccess = TRUE;
334 } /* finally */
335 __finally {
337 /* Cleanup and indicate failure, if appropriate. */
339 HeapFree(GetProcessHeap(), 0, ReferencedDomain);
341 if (!bSuccess) {
342 if (*Sid != NULL) {
343 HeapFree(GetProcessHeap(), 0, *Sid);
344 *Sid = NULL;
350 return (bSuccess);
353 NTSTATUS
354 SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
355 LPWSTR PrivilegeName, BOOL bEnable)
357 LSA_UNICODE_STRING PrivilegeString;
359 /* Create a LSA_UNICODE_STRING for the privilege name. */
360 InitLsaString(&PrivilegeString, PrivilegeName);
362 /* grant or revoke the privilege, accordingly */
363 if (bEnable)
364 return (LsaAddAccountRights(PolicyHandle, AccountSid,
365 &PrivilegeString, 1));
366 else
367 return (LsaRemoveAccountRights(PolicyHandle, AccountSid,
368 FALSE, &PrivilegeString, 1));
371 NTSTATUS
372 GetPrivilegesOnAccount(LSA_HANDLE PolicyHandle, PSID AccountSid,
373 wchar_t **PrivList, unsigned int *PrivCount)
375 NTSTATUS Status;
376 LSA_UNICODE_STRING *UserRights;
377 ULONG CountOfRights;
378 unsigned int retlen = 0;
379 DWORD i, j;
380 int found;
382 Status = LsaEnumerateAccountRights(PolicyHandle, AccountSid,
383 &UserRights, &CountOfRights);
384 /* Only continue if there is something */
385 if (UserRights == NULL || Status != STATUS_SUCCESS)
386 return (Status);
388 for (i = 0; i < CountOfRights; i++) {
389 found = -1;
390 retlen = UserRights[i].Length/sizeof(wchar_t);
391 for (j = 0; j < *PrivCount; j++) {
392 found = wcsncmp(PrivList[j], UserRights[i].Buffer,
393 retlen);
394 if (found == 0)
395 break;
397 if (found != 0) {
398 PrivList[*PrivCount] =
399 (wchar_t *)malloc(UserRights[i].MaximumLength);
400 if (PrivList[*PrivCount] == NULL)
401 return (RTN_NOMEMORY);
403 wcsncpy(PrivList[*PrivCount], UserRights[i].Buffer,
404 retlen);
405 PrivList[*PrivCount][retlen] = L'\0';
406 (*PrivCount)++;
411 return (Status);
414 void
415 DisplayNtStatus(LPSTR szAPI, NTSTATUS Status) {
416 /* Convert the NTSTATUS to Winerror. Then call DisplayWinError(). */
417 DisplayWinError(szAPI, LsaNtStatusToWinError(Status));
420 void
421 DisplayWinError(LPSTR szAPI, DWORD WinError) {
422 LPSTR MessageBuffer;
423 DWORD dwBufferLength;
425 if (dwBufferLength=FormatMessageA(
426 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
427 NULL, WinError, GetUserDefaultLangID(),
428 (LPSTR) &MessageBuffer, 0, NULL)){
429 DWORD dwBytesWritten; /* unused */
431 /* Output message string on stderr. */
432 WriteFile(GetStdHandle(STD_ERROR_HANDLE), MessageBuffer,
433 dwBufferLength, &dwBytesWritten, NULL);
435 /* Free the buffer allocated by the system. */
436 LocalFree(MessageBuffer);