feisty meow concerns codebase 2.140
nt_security.cpp
Go to the documentation of this file.
1
2
3
4/*****************************************************************************\
5* *
6* Name : nt_security *
7* Author : Sue Richeson *
8* Author : Chris Koeritz *
9* *
10*******************************************************************************
11* Copyright (c) 1999-$now By Author. This program is free software; you can *
12* redistribute it and/or modify it under the terms of the GNU General Public *
13* License as published by the Free Software Foundation; either version 2 of *
14* the License or (at your option) any later version. This is online at: *
15* http://www.fsf.org/copyleft/gpl.html *
16* Please send any updates to: fred@gruntose.com *
17\*****************************************************************************/
18
19#ifdef __WIN32__
20
21#include "nt_security.h"
22#include "win32_security.h"
23
24#include <basis/astring.h>
25
26#include <lm.h>
27
28// LSA success status value.
29#ifndef STATUS_SUCCESS
30 #define STATUS_SUCCESS ((NTSTATUS)0x00000000L)
31#endif
32
33nt_security::nt_security()
34: m_sDirServiceProvider(NULL_POINTER)
35{
36 // Eventually, construction of nt_security should determine if WinNT://
37 // or LDAP://, etc is the service provider and set a private member variable
38 // with the appropriate distinguished name qualifier.
39 m_sDirServiceProvider = new astring("WinNT://");
40}
41//---------------------------------------------------------------------------
42
43
44nt_security::~nt_security()
45{
46 if (m_sDirServiceProvider)
47 delete m_sDirServiceProvider;
48}
49
50
51//---------------------------------------------------------------------------
52
53bool nt_security::iequalsUsername(astring name1, astring name2)
54{
55 return normalizeUsername(name1) == normalizeUsername(name2);
56}
57
58const astring &nt_security::normalizeUsername(astring &username)
59{
60 username.replace_all('/', '\\');
61 username.replace_all('|', ':');
62 username.to_lower();
63 return username;
64}
65
66 //---------------------------------------------------------------------------
67
68astring nt_security::DomainBinding(const astring &domain)
69{
70 astring tempstring = *m_sDirServiceProvider + domain;
71 return (tempstring);
72}
73//---------------------------------------------------------------------------
74
75
76astring nt_security::DomainUserBinding(const astring &domain, const astring &user_name)
77{
78 astring tempstring = *m_sDirServiceProvider + domain + astring("/") + user_name;
79 return (tempstring);
80}
81//---------------------------------------------------------------------------
82
83// This piece of code is borrowed from the following July 1999 MSDN article
84// HOWTO: Look Up Current User Name and Domain Name
85// ID: Q155698
86//NOTE: It has been modified for inclusion in this class and it is NT-specific.
87
88bool nt_security::GetUserAndDomainName(astring &UserName, astring &DomainName)
89{
90 return win32_security::GetUserAndDomainName(UserName, DomainName);
91}
92
93
94//---------------------------------------------------------------------------
95// The following routines were taken from the lsapriv sample application by
96// Scott Field on the MSDN January 2001.
97//---------------------------------------------------------------------------
98
99/*---------------------------------------------------------------------------
100This function attempts to obtain a SID representing the supplied
101account on the supplied system.
102
103If the function succeeds, the return value is the SID. A buffer is
104allocated which contains the SID representing the supplied account.
105This buffer should be freed when it is no longer needed by calling
106HeapFree(GetProcessHeap(), 0, buffer)
107
108If the function fails, the return SID is NULL.
109
110Scott Field (sfield) 12-Jul-95
111Sue Richeson 27-FEB-2001 Mods for use in LightLink.
112Chris Koeritz 02-JAN-2008 changed some more for use within hoople.
113---------------------------------------------------------------------------*/
114
115PSID nt_security::GetUserSID(const astring &user_name)
116{
117 PSID psid = NULL;
118 char * ReferencedDomain = NULL;
119 DWORD cbSid = 128; // initial allocation attempt
120 DWORD cchReferencedDomain = 16; // initial allocation size
121 SID_NAME_USE peUse;
122 bool bSuccess = false;
123
124 try
125 { //
126 // initial memory allocations
127 //
128 psid = (PSID)HeapAlloc(GetProcessHeap(), 0, cbSid);
129 if (psid != NULL)
130 {
131 ReferencedDomain = (char *)HeapAlloc(GetProcessHeap(), 0, cchReferencedDomain * sizeof(TCHAR));
132 if (ReferencedDomain != NULL)
133 {
134 // Obtain the SID of the specified account on the specified system.
135 //
136 bSuccess = true;
137 while (!LookupAccountName(NULL, // machine to lookup account on
138 to_unicode_temp(user_name), // account to lookup
139 psid, // SID of interest
140 &cbSid, // size of SID
141 to_unicode_temp(ReferencedDomain), // domain where found.
142 &cchReferencedDomain,
143 &peUse))
144 {
145 if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
146 {
147 // reallocate memory
148 //
149 psid = (PSID)HeapReAlloc(GetProcessHeap(), 0, psid, cbSid);
150 if(psid != NULL)
151 {
152 ReferencedDomain = (char *)HeapReAlloc(GetProcessHeap(), 0,
153 ReferencedDomain,
154 cchReferencedDomain * sizeof(TCHAR));
155 if (ReferencedDomain == NULL)
156 {
157 break;
158 bSuccess = false;
159 }
160 }
161 else
162 {
163 break;
164 bSuccess = false;
165 }
166 }
167 else
168 {
169 break;
170 bSuccess = false;
171 }
172 } // end while
173 } // if ReferencedDomain
174 } // if psid
175 }
176 catch(...)
177 {
178 bSuccess = false;
179 }
180
181 // Cleanup and indicate failure, if appropriate.
182 //
183 if (ReferencedDomain != NULL)
184 HeapFree(GetProcessHeap(), 0, ReferencedDomain);
185
186 if (!bSuccess)
187 {
188 if (psid != NULL)
189 {
190 HeapFree(GetProcessHeap(), 0, psid);
191 psid = NULL;
192 }
193 }
194
195 return psid;
196}
197//---------------------------------------------------------------------------
198
199
200DWORD nt_security::OpenPolicy(const astring &serverName, DWORD DesiredAccess, PLSA_HANDLE pPolicyHandle)
201{
202 LSA_OBJECT_ATTRIBUTES ObjectAttributes;
203 NTSTATUS Status;
204 DWORD winerror = 0;
205
206 // Always initialize the object attributes to all zeroes.
207 //
208 ZeroMemory(&ObjectAttributes, sizeof(ObjectAttributes));
209
210 transcode_to_utf16 temp_server(serverName);
211 LSA_UNICODE_STRING server;
212 server.Buffer = (PWSTR)(UTF16 *)temp_server;
213 server.Length = serverName.length() * (int)sizeof(UTF16);
214 server.MaximumLength = (serverName.length() +1) * (int)sizeof(UTF16);
215
216 // Attempt to open the policy.
217 Status = LsaOpenPolicy(&server, &ObjectAttributes, DesiredAccess, pPolicyHandle);
218 if (STATUS_SUCCESS != Status)
219 {
220 winerror = LsaNtStatusToWinError(Status);
221 ClosePolicy(pPolicyHandle);
222 return winerror;
223 }
224 else
225 return winerror;
226}
227//---------------------------------------------------------------------------
228
229
230void nt_security::ClosePolicy(PLSA_HANDLE policyHandle)
231{
232 if (policyHandle != NULL)
233 LsaClose(policyHandle);
234}
235//---------------------------------------------------------------------------
236
237
238/*
239void nt_security::InitLsaString(LPWSTR inString, PLSA_UNICODE_STRING LsaString)
240{
241 DWORD StringLength;
242
243 if (inString == NULL)
244 {
245 LsaString->Buffer = NULL;
246 LsaString->Length = 0;
247 LsaString->MaximumLength = 0;
248 return;
249 }
250
251 StringLength = wcslen(inString);
252 LsaString->Buffer = inString;
253 LsaString->Length = (USHORT) StringLength * sizeof(WCHAR);
254 LsaString->MaximumLength=(USHORT)(StringLength+1) * sizeof(WCHAR);
255}
256*/
257//---------------------------------------------------------------------------
258
259
260DWORD nt_security::SetPrivilegeOnAccount(LSA_HANDLE PolicyHandle, // open policy handle
261 PSID AccountSid, // SID to grant privilege to
262 const astring &PrivilegeName, // privilege to grant (Unicode)
263 bool bEnable) // enable or disable
264{
265 NTSTATUS Status;
266 DWORD winerror = 0;
267
268 // Create a LSA_UNICODE_STRING for the privilege name.
269 //
270 transcode_to_utf16 temp_priv(PrivilegeName);
271 LSA_UNICODE_STRING privs;
272 privs.Buffer = (PWSTR)(UTF16 *)temp_priv;
273 privs.Length = PrivilegeName.length() * (int)sizeof(UTF16);
274 privs.MaximumLength = (PrivilegeName.length() +1) * (int)sizeof(UTF16);
275
276 // grant or revoke the privilege, accordingly
277 //
278 if (bEnable)
279 {
280 Status = LsaAddAccountRights(PolicyHandle, // open policy handle
281 AccountSid, // target SID
282 &privs, // privileges
283 1); // privilege count
284 }
285 else
286 {
287 Status = LsaRemoveAccountRights(PolicyHandle, // open policy handle
288 AccountSid, // target SID
289 FALSE, // do not disable all rights
290 &privs, // privileges
291 1); // privilege count
292 }
293
294 if (Status == STATUS_SUCCESS)
295 return winerror;
296 else
297 {
298 winerror = LsaNtStatusToWinError(Status);
299 return winerror;
300 }
301}
302//---------------------------------------------------------------------------
303
304
305DWORD nt_security::SetPrivilegeOnUser(const astring &domain,
306 const astring &user,
307 const astring &privilege,
308 bool bEnable)
309{
310 LSA_HANDLE policyHandle;
311 PSID psid = NULL;
312 DWORD winerror = 0;
313
314 // Open the policy on the target machine.
315 //
316 winerror = OpenPolicy(domain, (POLICY_CREATE_ACCOUNT | POLICY_LOOKUP_NAMES), &policyHandle);
317 if (winerror != 0)
318 return winerror;
319
320 // Obtain the SID of the user/group.
321 // Note that we could target a specific machine, but we don't.
322 // Specifying NULL for target machine searches for the SID in the
323 // following order: well-known, Built-in and local, primary domain,
324 // trusted domains.
325 //
326 psid = GetUserSID(user);
327 if (psid == NULL)
328 {
329 ClosePolicy(&policyHandle);
330 return ERROR_NO_SUCH_USER;
331 }
332
333 // Grant the SeServiceLogonRight to users represented by psid.
334 //
335 winerror = SetPrivilegeOnAccount(policyHandle, psid, privilege, bEnable);
336
337 // Close the policy handle.
338 //
339 ClosePolicy(&policyHandle);
340
341 //
342 // Free memory allocated for SID.
343 //
344 if (psid != NULL)
345 HeapFree(GetProcessHeap(), 0, psid);
346
347 return winerror;
348}
349
350DWORD nt_security::AddUserToGroup(const astring &user_name, const astring &group_name)
351{
352 LOCALGROUP_MEMBERS_INFO_3 lgmi3;
353 DWORD dwLevel = 3;
354 DWORD totalEntries = 1;
355 NET_API_STATUS nStatus;
356
357// fwprintf(stderr, L"Usage: %s ServerName GroupName MemberAccountName-(DomainName\\AccountName)\n", argv[0]);
358
359 // Set up the LOCALGROUP_MEMBERS_INFO_3 structure.
360 // Assign the member account name in form of DomainName\AccountName
361 transcode_to_utf16 temp_user(user_name);
362 lgmi3.lgrmi3_domainandname = (LPWSTR)(UTF16 *)temp_user;
363
364 // Call the NetLocalGroupAddMembers() function, specifying level 3.
365 // Level 0 can use SID
366 transcode_to_utf16 temp_group(group_name);
367 nStatus = NetLocalGroupAddMembers(L"", (LPWSTR)(UTF16 *)temp_group, dwLevel,
368 (LPBYTE)&lgmi3, totalEntries);
369
370//printf("got error code %d\n" , nStatus);
371
372 if (nStatus == ERROR_MEMBER_IN_ALIAS) nStatus = 0; // not an error.
373
374 return nStatus;
375}
376
377#endif //win32
378
379
380
#define NULL_POINTER
The value representing a pointer to nothing.
Definition definitions.h:32
unsigned short UTF16
unsigned long DWORD