Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

288 lines
8.7 KiB

  1. /*---------------------------------------------------------------------------
  2. File: ComputerPwdAge.cpp
  3. Comments: Implementation of COM object to retrieve password age for computer
  4. accounts (used to detect defunct computer accounts.)
  5. (c) Copyright 1999, Mission Critical Software, Inc., All Rights Reserved
  6. Proprietary and confidential to Mission Critical Software, Inc.
  7. REVISION LOG ENTRY
  8. Revision By: Christy Boles
  9. Revised on 02/15/99 11:19:31
  10. ---------------------------------------------------------------------------
  11. */
  12. // ComputerPwdAge.cpp : Implementation of CComputerPwdAge
  13. #include "stdafx.h"
  14. #include "WorkObj.h"
  15. #include "PwdAge.h"
  16. #include "Common.hpp"
  17. #include "UString.hpp"
  18. #include "Err.hpp"
  19. #include "CommaLog.hpp"
  20. #include "EaLen.hpp"
  21. #include "GetDcName.h"
  22. //#import "\bin\McsVarSetMin.tlb" no_namespace
  23. //#import "\bin\DBManager.tlb" no_namespace, named_guids
  24. #import "VarSet.tlb" no_namespace rename("property", "aproperty")
  25. #import "DBMgr.tlb" no_namespace, named_guids
  26. #include <lm.h>
  27. /////////////////////////////////////////////////////////////////////////////
  28. // CComputerPwdAge
  29. STDMETHODIMP
  30. CComputerPwdAge::SetDomain(
  31. BSTR domain // in - domain name to examine
  32. )
  33. {
  34. HRESULT hr = S_OK;
  35. DWORD rc;
  36. WCHAR domctrl[LEN_Computer];
  37. if ( UStrICmp(m_Domain,domain) )
  38. {
  39. m_Domain = domain;
  40. rc = GetDomainControllerForDomain(domain,domctrl);
  41. if ( rc )
  42. {
  43. hr = HRESULT_FROM_WIN32(rc);
  44. }
  45. else
  46. {
  47. m_DomainCtrl = domctrl;
  48. }
  49. }
  50. return hr;
  51. }
  52. STDMETHODIMP
  53. CComputerPwdAge::GetPwdAge(
  54. BSTR domain, // in - domain name to examine
  55. BSTR ComputerName, // in - machine name of computer
  56. DWORD * pPwdAge // out- password age in seconds
  57. )
  58. {
  59. HRESULT hr;
  60. DWORD rc;
  61. WCHAR computerAccountName[LEN_Account];
  62. DWORD pwdage = 0;
  63. hr = SetDomain(domain);
  64. if ( SUCCEEDED(hr) )
  65. {
  66. swprintf(computerAccountName,L"%s",ComputerName);
  67. rc = GetSinglePasswordAgeInternal(m_DomainCtrl,computerAccountName,&pwdage);
  68. if ( ! rc )
  69. {
  70. (*pPwdAge) = pwdage;
  71. }
  72. else
  73. {
  74. hr = HRESULT_FROM_WIN32(rc);
  75. }
  76. }
  77. return hr;
  78. }
  79. STDMETHODIMP
  80. CComputerPwdAge::ExportPasswordAge(
  81. BSTR domain, // in - domain to export information from
  82. BSTR filename // in - UNC name of file to write information to
  83. )
  84. {
  85. HRESULT hr;
  86. hr = SetDomain(domain);
  87. if ( SUCCEEDED(hr) )
  88. {
  89. hr = ExportPasswordAgeOlderThan(domain,filename,0);
  90. }
  91. return hr;
  92. }
  93. STDMETHODIMP
  94. CComputerPwdAge::ExportPasswordAgeOlderThan(
  95. BSTR domain, // in - domain to export information from
  96. BSTR filename, // in - filename to write information to
  97. DWORD minAge // in - write only accounts with password age older than minAge
  98. )
  99. {
  100. DWORD rc = 0;
  101. HRESULT hr;
  102. hr = SetDomain(domain);
  103. if ( SUCCEEDED(hr) )
  104. {
  105. rc = ExportPasswordAgeInternal(m_DomainCtrl,filename,minAge,TRUE);
  106. if ( rc )
  107. {
  108. hr = HRESULT_FROM_WIN32(rc);
  109. }
  110. }
  111. return hr;
  112. }
  113. STDMETHODIMP
  114. CComputerPwdAge::ExportPasswordAgeNewerThan(
  115. BSTR domain, // in - domain to export information from
  116. BSTR filename, // in - filename to write information to
  117. DWORD maxAge // in - write only computer accounts with password age less than maxAge
  118. )
  119. {
  120. DWORD rc = 0;
  121. HRESULT hr;
  122. hr = SetDomain(domain);
  123. if ( SUCCEEDED(hr) )
  124. {
  125. rc = ExportPasswordAgeInternal(m_DomainCtrl,filename,maxAge,FALSE);
  126. if ( rc )
  127. {
  128. hr = HRESULT_FROM_WIN32(rc);
  129. }
  130. }
  131. return hr;
  132. }
  133. DWORD // ret- WIN32 error code
  134. CComputerPwdAge::GetDomainControllerForDomain(
  135. WCHAR const * domain, // in - name of domain
  136. WCHAR * domctrl // out- domain controller for domain
  137. )
  138. {
  139. DWORD rc;
  140. _bstr_t result;
  141. rc = GetAnyDcName4(domain, result);
  142. if ( ! rc )
  143. {
  144. wcscpy(domctrl,result);
  145. }
  146. return rc;
  147. }
  148. DWORD // ret- WIN32 error code
  149. CComputerPwdAge::ExportPasswordAgeInternal(
  150. WCHAR const * domctrl, // in - domain controller to query
  151. WCHAR const * filename, // in - filename to write results to
  152. DWORD minOrMaxAge, // in - optional min or max age to write
  153. BOOL bOld // in - TRUE-Age is min age, copies only old accounts
  154. )
  155. {
  156. DWORD rc = 0;
  157. DWORD nRead;
  158. DWORD nTotal;
  159. DWORD nResume = 0;
  160. DWORD prefmax = 1000;
  161. USER_INFO_11 * buf;
  162. time_t pwdage; // the number of seconds ago that the pwd was last changed
  163. time_t pwdtime; // the time when the pwd was last changed
  164. time_t now; // the current time
  165. CommaDelimitedLog log;
  166. IIManageDBPtr pDB;
  167. WCHAR computerName[LEN_Account];
  168. rc = pDB.CreateInstance(CLSID_IManageDB);
  169. if ( SUCCEEDED(rc) )
  170. {
  171. time(&now);
  172. do
  173. {
  174. rc = NetUserEnum(domctrl,11,FILTER_WORKSTATION_TRUST_ACCOUNT,(LPBYTE*)&buf,prefmax,&nRead,&nTotal,&nResume);
  175. if ( rc && rc != ERROR_MORE_DATA )
  176. break;
  177. for ( UINT i = 0 ; i < nRead ; i++ )
  178. {
  179. pwdage = buf[i].usri11_password_age;
  180. if ( ( pwdage >= (time_t)minOrMaxAge && bOld ) // inactive machines
  181. ||( pwdage <= (time_t)minOrMaxAge && !bOld ) ) // active machines
  182. {
  183. safecopy(computerName,buf[i].usri11_name);
  184. // strip off the $ from the end of the computer account
  185. computerName[UStrLen(computerName)-1] = 0;
  186. // pDB->raw_SavePasswordAge(m_Domain,SysAllocString(computerName),SysAllocString(buf[i].usri11_comment),pwdage);
  187. pDB->raw_SavePasswordAge(m_Domain,SysAllocString(computerName),SysAllocString(buf[i].usri11_comment),(long)pwdage);
  188. pwdtime = now - pwdage;
  189. }
  190. }
  191. NetApiBufferFree(buf);
  192. } while ( rc == ERROR_MORE_DATA );
  193. }
  194. else
  195. {
  196. rc = GetLastError();
  197. }
  198. return rc;
  199. }
  200. DWORD // ret- WIN32 error code
  201. CComputerPwdAge::GetSinglePasswordAgeInternal(
  202. WCHAR const * domctrl, // in - domain controller to query
  203. WCHAR const * computer, // in - name of computer account
  204. DWORD * pwdage // out- password age in seconds
  205. )
  206. {
  207. DWORD rc = 0;
  208. USER_INFO_11 * buf;
  209. rc = NetUserGetInfo(domctrl,computer,11,(LPBYTE*)&buf);
  210. if (! rc )
  211. {
  212. (*pwdage) = buf->usri11_password_age;
  213. NetApiBufferFree(buf);
  214. }
  215. return rc;
  216. }
  217. // ComputerPwdAge worknode
  218. // Retrieves the password age (in seconds) for a computer account in a specified domain
  219. // This can be used to identify defunct computer accounts
  220. //
  221. // VarSet syntax
  222. // Input:
  223. // ComputerPasswordAge.Domain: <DomainName>
  224. // ComputerPasswordAge.Computer: <ComputerName>
  225. // Output:
  226. // ComputerPasswordAge.Seconds : <number>
  227. STDMETHODIMP
  228. CComputerPwdAge::Process(
  229. IUnknown * pWorkItem // in - varset containing settings
  230. )
  231. {
  232. HRESULT hr = S_OK;
  233. IVarSetPtr pVarSet = pWorkItem;
  234. _bstr_t domain;
  235. _bstr_t computer;
  236. DWORD age;
  237. domain = pVarSet->get(L"ComputerPasswordAge.Domain");
  238. computer = pVarSet->get(L"ComputerPasswordAge.Computer");
  239. if ( computer.length() && domain.length() )
  240. {
  241. hr = GetPwdAge(domain,computer,&age);
  242. if ( SUCCEEDED(hr) )
  243. {
  244. pVarSet->put(L"ComputerPasswordAge.Seconds",(LONG)age);
  245. }
  246. }
  247. return hr;
  248. }