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.

426 lines
14 KiB

  1. // CSvcInf.cpp : Implementation of CCSvcAcctInfo
  2. #include "stdafx.h"
  3. #include "McsPISag.h"
  4. //#import "\bin\McsVarSetMin.tlb" no_namespace, named_guids
  5. //#import "\bin\DBManager.tlb" no_namespace, named_guids
  6. #import "VarSet.tlb" no_namespace, named_guids rename("property", "aproperty")
  7. #import "DBMgr.tlb" no_namespace, named_guids
  8. #include "CSvcInf.h"
  9. #include "ResStr.h"
  10. #include "ErrDct.hpp"
  11. #include <ntdsapi.h>
  12. #include <lm.h>
  13. #include "GetDcName.h"
  14. // these are needed for ISecPlugIn
  15. #include "cipher.hpp"
  16. #include "SecPI.h"
  17. #define EXCHANGE_SERVICE_NAME L"MSExchangeSA"
  18. #define SvcAcctStatus_DoNotUpdate 1
  19. #define SvcAcctStatus_NeverAllowUpdate 8
  20. TErrorDct err;
  21. /////////////////////////////////////////////////////////////////////////////
  22. // CCSvcAcctInfo
  23. typedef UINT (CALLBACK* DSBINDFUNC)(TCHAR*, TCHAR*, HANDLE*);
  24. typedef UINT (CALLBACK* DSUNBINDFUNC)(HANDLE*);
  25. typedef NTDSAPI
  26. DWORD
  27. WINAPI
  28. DSCRACKNAMES(
  29. HANDLE hDS, // in
  30. DS_NAME_FLAGS flags, // in
  31. DS_NAME_FORMAT formatOffered, // in
  32. DS_NAME_FORMAT formatDesired, // in
  33. DWORD cNames, // in
  34. const LPCWSTR *rpNames, // in
  35. PDS_NAME_RESULTW *ppResult); // out
  36. typedef NTDSAPI
  37. void
  38. WINAPI
  39. DSFREENAMERESULT(
  40. DS_NAME_RESULTW *pResult
  41. );
  42. // This method is called by the dispatcher to verify that this is a valid plug-in
  43. // Only valid plug-ins will be sent out with the agents
  44. // The purpose of this check is to make it more difficult for unauthorized parties
  45. // to use our plug-in interface, since it is currently undocumented.
  46. STDMETHODIMP CCSvcAcctInfo::Verify(/*[in,out]*/ULONG * pData,/*[in]*/ULONG size)
  47. {
  48. McsChallenge * pMcsChallenge;
  49. long lTemp1;
  50. long lTemp2;
  51. if( size == sizeof(McsChallenge) )
  52. {
  53. pMcsChallenge = (McsChallenge*)(pData);
  54. SimpleCipher((LPBYTE)pMcsChallenge,size);
  55. pMcsChallenge->MCS[0] = 'M';
  56. pMcsChallenge->MCS[1] = 'C';
  57. pMcsChallenge->MCS[2] = 'S';
  58. pMcsChallenge->MCS[3] = 0;
  59. lTemp1 = pMcsChallenge->lRand1 + pMcsChallenge->lRand2;
  60. lTemp2 = pMcsChallenge->lRand2 - pMcsChallenge->lRand1;
  61. pMcsChallenge->lRand1 = lTemp1;
  62. pMcsChallenge->lRand2 = lTemp2;
  63. pMcsChallenge->lTime += 100;
  64. SimpleCipher((LPBYTE)pMcsChallenge,size);
  65. }
  66. else
  67. return E_FAIL;
  68. return S_OK;
  69. }
  70. STDMETHODIMP CCSvcAcctInfo::GetRegisterableFiles(/* [out] */SAFEARRAY ** pArray)
  71. {
  72. SAFEARRAYBOUND bound[1] = { 1, 0 };
  73. LONG ndx[1] = { 0 };
  74. (*pArray) = SafeArrayCreate(VT_BSTR,1,bound);
  75. SafeArrayPutElement(*pArray,ndx,SysAllocString(L"McsPISag.DLL"));
  76. return S_OK;
  77. }
  78. STDMETHODIMP CCSvcAcctInfo::GetRequiredFiles(/* [out] */SAFEARRAY ** pArray)
  79. {
  80. SAFEARRAYBOUND bound[1] = { 1, 0 };
  81. LONG ndx[1] = { 0 };
  82. (*pArray) = SafeArrayCreate(VT_BSTR,1,bound);
  83. SafeArrayPutElement(*pArray,ndx,SysAllocString(L"McsPISag.DLL"));
  84. return S_OK;
  85. }
  86. STDMETHODIMP CCSvcAcctInfo::GetDescription(/* [out] */ BSTR * description)
  87. {
  88. (*description) = SysAllocString(L"");
  89. return S_OK;
  90. }
  91. STDMETHODIMP CCSvcAcctInfo::PreMigrationTask(/* [in] */IUnknown * pVarSet)
  92. {
  93. return S_OK;
  94. }
  95. STDMETHODIMP CCSvcAcctInfo::PostMigrationTask(/* [in] */IUnknown * pVarSet)
  96. {
  97. // DWORD rc = 0;
  98. IVarSetPtr pVS;
  99. pVS = pVarSet;
  100. _bstr_t log = pVS->get(GET_BSTR(DCTVS_Options_Logfile));
  101. err.LogOpen((WCHAR*)log,1);
  102. err.MsgWrite(0,DCT_MSG_MCSPISAG_STARTING);
  103. pVS->put(GET_BSTR(DCTVS_CurrentOperation),GET_BSTR(IDS_Gathering_SvcAcct));
  104. ProcessServices(pVS);
  105. pVS->put(GET_BSTR(DCTVS_CurrentOperation),L"");
  106. err.MsgWrite(0,DCT_MSG_MCSPISAG_DONE);
  107. err.LogClose();
  108. return S_OK;
  109. }
  110. STDMETHODIMP CCSvcAcctInfo::GetName(/* [out] */BSTR * name)
  111. {
  112. (*name) = SysAllocString(L"");
  113. return S_OK;
  114. }
  115. STDMETHODIMP CCSvcAcctInfo::GetResultString(/* [in] */IUnknown * pVarSet,/* [out] */ BSTR * text)
  116. {
  117. WCHAR buffer[1000] = L"";
  118. IVarSetPtr pVS;
  119. pVS = pVarSet;
  120. (*text) = SysAllocString(buffer);
  121. return S_OK;
  122. }
  123. STDMETHODIMP CCSvcAcctInfo::StoreResults(/* [in] */IUnknown * pVarSet)
  124. {
  125. IVarSetPtr pVS = pVarSet;
  126. IIManageDBPtr pDatabase;
  127. HRESULT hr;
  128. WCHAR key[200];
  129. _bstr_t service;
  130. _bstr_t account;
  131. _bstr_t computer;
  132. _bstr_t display;
  133. long ndx = 0;
  134. _bstr_t exchangeAccount;
  135. HINSTANCE hLibrary = NULL;
  136. DSCRACKNAMES * DsCrackNames = NULL;
  137. DSFREENAMERESULT * DsFreeNameResult = NULL;
  138. DSBINDFUNC DsBind = NULL;
  139. DSUNBINDFUNC DsUnBind = NULL;
  140. _bstr_t sourceDomainDns = pVS->get(GET_BSTR(DCTVS_Options_SourceDomainDns));
  141. WCHAR * atPtr = NULL;
  142. HANDLE hDs = NULL;
  143. computer = pVS->get("LocalServer");
  144. hr = pDatabase.CreateInstance(CLSID_IManageDB);
  145. if ( SUCCEEDED(hr) )
  146. {
  147. // make a pre-pass through the data
  148. do
  149. {
  150. swprintf(key,L"ServiceAccounts.%ld.Service",ndx);
  151. service = pVS->get(key);
  152. swprintf(key,L"ServiceAccounts.%ld.Account",ndx);
  153. account = pVS->get(key);
  154. // make sure the account names are not in UPN format
  155. if ( NULL == wcschr((WCHAR*)account,L'\\') )
  156. {
  157. if (! hDs )
  158. {
  159. if (! hLibrary )
  160. {
  161. hLibrary = LoadLibrary(L"NTDSAPI.DLL");
  162. }
  163. if ( hLibrary )
  164. {
  165. DsBind = (DSBINDFUNC)GetProcAddress(hLibrary,"DsBindW");
  166. DsUnBind = (DSUNBINDFUNC)GetProcAddress(hLibrary,"DsUnBindW");
  167. DsCrackNames = (DSCRACKNAMES *)GetProcAddress(hLibrary,"DsCrackNamesW");
  168. DsFreeNameResult = (DSFREENAMERESULT *)GetProcAddress(hLibrary,"DsFreeNameResultW");
  169. }
  170. if ( DsBind && DsUnBind && DsCrackNames && DsFreeNameResult)
  171. {
  172. hr = (*DsBind)(NULL,(WCHAR*)sourceDomainDns,&hDs);
  173. if ( hr )
  174. {
  175. hDs = NULL;
  176. }
  177. }
  178. }
  179. if ( hDs )
  180. {
  181. PDS_NAME_RESULT pNamesOut = NULL;
  182. WCHAR * pNamesIn[1];
  183. pNamesIn[0] = (WCHAR*)account;
  184. hr = (*DsCrackNames)(hDs,DS_NAME_NO_FLAGS,DS_USER_PRINCIPAL_NAME,DS_NT4_ACCOUNT_NAME,1,pNamesIn,&pNamesOut);
  185. (*DsUnBind)(&hDs);
  186. hDs = NULL;
  187. if ( !hr )
  188. {
  189. if ( pNamesOut->rItems[0].status == DS_NAME_NO_ERROR )
  190. {
  191. account = pNamesOut->rItems[0].pName;
  192. pVS->put(key,account);
  193. }
  194. //if from another domain try connecting to that domain's DC and
  195. //retry DSCrackNames
  196. else if ( pNamesOut->rItems[0].status == DS_NAME_ERROR_DOMAIN_ONLY )
  197. {
  198. _bstr_t dc;
  199. DWORD dwError = GetAnyDcName4(pNamesOut->rItems[0].pDomain, dc);
  200. if (dwError == ERROR_SUCCESS)
  201. {
  202. //bind to that domain DC
  203. hr = (*DsBind)(dc,NULL,&hDs);
  204. if ( !hr )
  205. {
  206. (*DsFreeNameResult)(pNamesOut);//release the old info
  207. pNamesOut = NULL;
  208. //retry DSCrackNames again
  209. hr = (*DsCrackNames)(hDs,DS_NAME_NO_FLAGS,DS_USER_PRINCIPAL_NAME,DS_NT4_ACCOUNT_NAME,1,pNamesIn,&pNamesOut);
  210. if ( !hr )
  211. {
  212. if ( pNamesOut->rItems[0].status == DS_NAME_NO_ERROR )
  213. {
  214. account = pNamesOut->rItems[0].pName;
  215. pVS->put(key,account);
  216. }
  217. }
  218. (*DsUnBind)(&hDs);
  219. hDs = NULL;
  220. }
  221. }
  222. }
  223. if (pNamesOut)
  224. (*DsFreeNameResult)(pNamesOut);
  225. }
  226. }
  227. }
  228. // also, look for the exchange server service account
  229. if ( !UStrICmp(service,EXCHANGE_SERVICE_NAME) )
  230. {
  231. exchangeAccount = account;
  232. }
  233. ndx++;
  234. } while ( service.length() );
  235. ndx = 0;
  236. WCHAR serverFilter[300];
  237. // clear any old entries from the table for this computer
  238. swprintf(serverFilter,L"System = '%ls'",(WCHAR*)computer);
  239. _variant_t Filter = serverFilter;
  240. hr = pDatabase->raw_ClearTable(SysAllocString(L"ServiceAccounts"), Filter);
  241. do
  242. {
  243. swprintf(key,L"ServiceAccounts.%ld.Service",ndx);
  244. service = pVS->get(key);
  245. swprintf(key,L"ServiceAccounts.%ld.DisplayName",ndx);
  246. display = pVS->get(key);
  247. swprintf(key,L"ServiceAccounts.%ld.Account",ndx);
  248. account = pVS->get(key);
  249. if ( service.length() && account.length() )
  250. {
  251. hr = pDatabase->raw_SetServiceAccount(computer,service,display,account);
  252. if ( SUCCEEDED(hr) && !UStrICmp((WCHAR*)account,(WCHAR*)exchangeAccount) )
  253. {
  254. // mark this account to be excluded from the processing
  255. hr = pDatabase->raw_SetServiceAcctEntryStatus(computer,service,account,SvcAcctStatus_NeverAllowUpdate);
  256. }
  257. }
  258. ndx++;
  259. } while ( service.length() );
  260. }
  261. if ( hLibrary )
  262. {
  263. FreeLibrary(hLibrary);
  264. }
  265. return S_OK;
  266. }
  267. STDMETHODIMP CCSvcAcctInfo::ConfigureSettings(/*[in]*/IUnknown * pVarSet)
  268. {
  269. IVarSetPtr pVS = pVarSet;
  270. MessageBox(NULL,L"This is a test",L"McsPISag PlugIn",MB_OK);
  271. return S_OK;
  272. }
  273. void CCSvcAcctInfo::ProcessServices(IVarSet * pVarSet)
  274. {
  275. // Connect to the SCM on the local computer
  276. SC_HANDLE pScm = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS );
  277. DWORD rc = 0;
  278. WCHAR domain[200];
  279. WKSTA_INFO_100 * info;
  280. // Get the name of the domain that this computer is in, so we can resolve any accounts that are
  281. // specified as .\Account to DOMAIN\account format
  282. rc = NetWkstaGetInfo(NULL,100,(BYTE**)&info);
  283. if ( ! rc )
  284. {
  285. UStrCpy(domain,info->wki100_langroup);
  286. NetApiBufferFree(info);
  287. }
  288. else
  289. {
  290. // if we can't get the domain name, just leave the .
  291. UStrCpy(domain,L".");
  292. }
  293. if ( pScm )
  294. {
  295. // Enumerate the services on the computer
  296. ENUM_SERVICE_STATUS servStatus[1000];
  297. DWORD cbBufSize = (sizeof servStatus);
  298. DWORD cbBytesNeeded = 0;
  299. DWORD nReturned = 0;
  300. DWORD hResume = 0;
  301. WCHAR string[1000];
  302. long count = 0;
  303. if (! EnumServicesStatus(pScm,SERVICE_WIN32,SERVICE_STATE_ALL,servStatus,cbBufSize,&cbBytesNeeded,&nReturned,&hResume) )
  304. {
  305. rc = GetLastError();
  306. err.SysMsgWrite(ErrE,rc,DCT_MSG_SERVICE_ENUM_FAILED_D,rc);
  307. }
  308. else
  309. {
  310. rc = 0;
  311. }
  312. if ( rc == ERROR_SUCCESS || rc == ERROR_MORE_DATA )
  313. {
  314. for ( UINT i = 0 ; i < nReturned ; i++ )
  315. {
  316. SC_HANDLE pService = OpenService(pScm,servStatus[i].lpServiceName,SERVICE_ALL_ACCESS );
  317. BYTE buf[3000];
  318. QUERY_SERVICE_CONFIG * pConfig = (QUERY_SERVICE_CONFIG *)buf;
  319. // BOOL bIncluded = FALSE;
  320. DWORD lenNeeded = 0;
  321. if ( pService )
  322. {
  323. // get the information about this service
  324. if ( QueryServiceConfig(pService,pConfig,sizeof buf, &lenNeeded) )
  325. {
  326. err.MsgWrite(0,DCT_MSG_SERVICE_USES_ACCOUNT_SS,servStatus[i].lpServiceName,pConfig->lpServiceStartName);
  327. // add the account to the list if it is not using LocalSystem or NT Authority account
  328. // or local accounts
  329. if ((UStrICmp(pConfig->lpServiceStartName,L"LocalSystem")) &&
  330. (_wcsnicmp(pConfig->lpServiceStartName, L"NT Authority\\", wcslen(L"NT Authority\\"))) &&
  331. (_wcsnicmp(pConfig->lpServiceStartName, L".\\", wcslen(L".\\"))))
  332. {
  333. swprintf(string,L"ServiceAccounts.%ld.Service",count);
  334. pVarSet->put(string,servStatus[i].lpServiceName);
  335. swprintf(string,L"ServiceAccounts.%ld.DisplayName",count);
  336. pVarSet->put(string,servStatus[i].lpDisplayName);
  337. swprintf(string,L"ServiceAccounts.%ld.Account",count);
  338. pVarSet->put(string,pConfig->lpServiceStartName);
  339. count++;
  340. }
  341. }
  342. CloseServiceHandle(pService);
  343. }
  344. else
  345. {
  346. err.SysMsgWrite(ErrE,GetLastError(),DCT_MSG_OPEN_SERVICE_FAILED_SD,servStatus[i].lpServiceName,rc);
  347. }
  348. }
  349. }
  350. CloseServiceHandle(pScm);
  351. }
  352. else
  353. {
  354. rc = GetLastError();
  355. err.SysMsgWrite(ErrE,rc,DCT_MSG_SCM_OPEN_FAILED_D,rc);
  356. }
  357. }