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 
33 nt_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 
44 nt_security::~nt_security()
45 {
46  if (m_sDirServiceProvider)
47  delete m_sDirServiceProvider;
48 }
49 
50 
51 //---------------------------------------------------------------------------
52 
53 bool nt_security::iequalsUsername(astring name1, astring name2)
54 {
55  return normalizeUsername(name1) == normalizeUsername(name2);
56 }
57 
58 const 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 
68 astring nt_security::DomainBinding(const astring &domain)
69 {
70  astring tempstring = *m_sDirServiceProvider + domain;
71  return (tempstring);
72 }
73 //---------------------------------------------------------------------------
74 
75 
76 astring 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 
88 bool 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 /*---------------------------------------------------------------------------
100 This function attempts to obtain a SID representing the supplied
101 account on the supplied system.
102 
103 If the function succeeds, the return value is the SID. A buffer is
104 allocated which contains the SID representing the supplied account.
105 This buffer should be freed when it is no longer needed by calling
106 HeapFree(GetProcessHeap(), 0, buffer)
107 
108 If the function fails, the return SID is NULL.
109 
110 Scott Field (sfield) 12-Jul-95
111 Sue Richeson 27-FEB-2001 Mods for use in LightLink.
112 Chris Koeritz 02-JAN-2008 changed some more for use within hoople.
113 ---------------------------------------------------------------------------*/
114 
115 PSID 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 
200 DWORD 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 
230 void nt_security::ClosePolicy(PLSA_HANDLE policyHandle)
231 {
232  if (policyHandle != NULL)
233  LsaClose(policyHandle);
234 }
235 //---------------------------------------------------------------------------
236 
237 
238 /*
239 void 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 
260 DWORD 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 
305 DWORD 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 
350 DWORD 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