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