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.

421 lines
14 KiB

  1. /*++
  2. Copyright (c) 1998 Microsoft Corporation
  3. Module Name:
  4. FixUp.cpp
  5. Abstract:
  6. Fix up Routines for Rolling Upgrades
  7. Author:
  8. Sunita Shrivastava(sunitas) 18-Mar-1998
  9. Galen Barbee (galenb) 31-Mar-1998
  10. Revision History:
  11. --*/
  12. #include "apip.h"
  13. //extern "C"
  14. //{
  15. //extern ULONG CsLogLevel;
  16. //extern ULONG CsLogModule;
  17. //}
  18. //static WCHAR wszPropertyName [] = { CLUSREG_NAME_CLUS_SD };
  19. //typedef struct stSecurityDescriptorProp
  20. //{
  21. // DWORD dwPropCount;
  22. // CLUSPROP_PROPERTY_NAME pnPropName;
  23. // WCHAR wszPropName [( sizeof( wszPropertyName ) / sizeof( WCHAR ) )];
  24. // CLUSPROP_BINARY biValueHeader;
  25. // BYTE rgbValueData[1];
  26. //} SECURITYPROPERTY;
  27. DWORD
  28. ApipAddNetServiceSidToSD(
  29. PSECURITY_DESCRIPTOR CurrentSD,
  30. PSECURITY_DESCRIPTOR * UpdatedSD
  31. )
  32. /*++
  33. Routine Description:
  34. If necessary, add the Network Service SID to the cluster security
  35. descriptor.
  36. REMOVE AFTER 1st MAJOR RELEASE AFTER WINDOWS XP/SERVER 2003 HAS SHIPPED,
  37. I.E. DURING THE DEV CYCLE OF WHISTLER + 2
  38. Arguments:
  39. CurrentSD - current NT5 based security descriptor
  40. UpdatedSD - address of pointer that receives SD with service SID added. If
  41. the SID is already present, the pointer is set to NULL.
  42. Return Value:
  43. ERROR_SUCCESS if everything worked ok
  44. --*/
  45. {
  46. DWORD status = ERROR_SUCCESS;
  47. PSID pNetServiceSid = NULL;
  48. PACL dacl = NULL;
  49. BOOL daclPresent;
  50. BOOL defaultDacl;
  51. BOOL success;
  52. DWORD aceIndex = 0;
  53. SID_IDENTIFIER_AUTHORITY siaNtAuthority = SECURITY_NT_AUTHORITY;
  54. //
  55. // make sure the passed in SD is valid
  56. //
  57. if ( !IsValidSecurityDescriptor( CurrentSD )) {
  58. ClRtlLogPrint(LOG_CRITICAL,
  59. "[API] Cluster Security Descriptor is not valid! Unable to add Network Service account.\n");
  60. status = ERROR_INVALID_SECURITY_DESCR;
  61. goto cleanup;
  62. }
  63. //
  64. // allocate and init the Network Service sid
  65. //
  66. if ( !AllocateAndInitializeSid( &siaNtAuthority,
  67. 1,
  68. SECURITY_NETWORK_SERVICE_RID,
  69. 0, 0, 0, 0, 0, 0, 0,
  70. &pNetServiceSid ) )
  71. {
  72. status = GetLastError();
  73. ClRtlLogPrint(LOG_CRITICAL,
  74. "[API] Can't get SID for Network Service account (status %1!u!)! "
  75. "Unable to add Network Service account to cluster security descriptor.\n",
  76. status);
  77. goto cleanup;
  78. }
  79. //
  80. // see if it is already in there; get a pointer to the DACL and run down
  81. // the ACES, comparing their SIDs to the Network Service SID
  82. //
  83. success = GetSecurityDescriptorDacl( CurrentSD, &daclPresent, &dacl, &defaultDacl );
  84. if ( !success ) {
  85. status = GetLastError();
  86. ClRtlLogPrint(LOG_CRITICAL,
  87. "[API] Failed to get DACL in cluster security descriptor - status %1!u!\n",
  88. status);
  89. goto cleanup;
  90. }
  91. if ( !daclPresent ) {
  92. //
  93. // no DACL present. Normally, the SD is present but downlevel (W2K)
  94. // nodes can delete the security properties.
  95. //
  96. ClRtlLogPrint(LOG_CRITICAL,
  97. "[API] DACL not present in cluster security descriptor.\n" );
  98. status = ERROR_INVALID_SECURITY_DESCR;
  99. goto cleanup;
  100. }
  101. for ( aceIndex = 0; aceIndex < dacl->AceCount; ++aceIndex ) {
  102. PACE_HEADER aceHeader;
  103. PSID aceSid = NULL;
  104. success = GetAce( dacl, aceIndex, (LPVOID *)&aceHeader );
  105. if ( !success ) {
  106. status = GetLastError();
  107. break;
  108. }
  109. //
  110. // we currently only support access allowed and denied ACEs, i.e., no
  111. // other ACE type should be present in the DACL.
  112. //
  113. if ( aceHeader->AceType == ACCESS_ALLOWED_ACE_TYPE ) {
  114. aceSid = &((ACCESS_ALLOWED_ACE *)aceHeader)->SidStart;
  115. }
  116. else if ( aceHeader->AceType == ACCESS_DENIED_ACE_TYPE ) {
  117. aceSid = &((ACCESS_DENIED_ACE *)aceHeader)->SidStart;
  118. }
  119. if ( aceSid != NULL ) {
  120. if ( EqualSid( pNetServiceSid, aceSid )) {
  121. #if DBG
  122. ClRtlLogPrint(LOG_NOISE,
  123. "[API] Network Service SID is already present in cluster security descriptor.\n" );
  124. #endif
  125. break;
  126. }
  127. }
  128. }
  129. if ( status == ERROR_SUCCESS && aceIndex == dacl->AceCount ) {
  130. //
  131. // didn't find it; add the Network Service SID
  132. //
  133. status = ClRtlAddAceToSd( CurrentSD, pNetServiceSid, CLUSAPI_ALL_ACCESS, UpdatedSD );
  134. if ( status != ERROR_SUCCESS ) {
  135. ClRtlLogPrint(LOG_CRITICAL,
  136. "[API] Unable to add Network Service account to cluster security "
  137. "descriptor, (status %1!u!).\n",
  138. status);
  139. goto cleanup;
  140. }
  141. } else if ( status != ERROR_SUCCESS ) {
  142. ClRtlLogPrint(LOG_NOISE,
  143. "[API] Failed to get ACE #%1!u! in cluster security descriptor - status %2!u!.\n",
  144. aceIndex,
  145. status);
  146. }
  147. cleanup:
  148. if ( pNetServiceSid != NULL ) {
  149. FreeSid( pNetServiceSid );
  150. }
  151. return status;
  152. } // ApipAddNetServiceSidToSD
  153. /****
  154. @func DWORD | ApiFixNotifyCb | If a cluster component wants to make
  155. a fixup to the cluster registry as a part of form/join it
  156. must register with the NM via this API.
  157. @parm IN PVOID| pContext | A pointer to the context information passed
  158. to NmRegisterFixupCb().
  159. @parm IN PVOID *ppPropertyList |
  160. @parm IN PVOID pdwProperyListSize | A pointer to DWORD where the size
  161. of the property list structure is returned.
  162. @comm For Whister/Windows Server 2003, the Network Service SID is added to the cluster
  163. security descriptor as well as the standard things for NT5. For
  164. NT 5.0, the api layer performs the fixup for the security
  165. descriptor. If the new security descriptor entry for the cluster is
  166. not present in the registry, convert the old format to the new one
  167. and write it to the cluster registry.
  168. @rdesc Returns a result code. ERROR_SUCCESS on success.
  169. @xref <f NmJoinFixup> <f NmFormFixup>
  170. *****/
  171. extern "C" DWORD
  172. ApiFixupNotifyCb(
  173. IN DWORD dwFixupType,
  174. OUT PVOID *ppPropertyList,
  175. OUT LPDWORD pdwPropertyListSize,
  176. OUT LPWSTR *pszKeyName
  177. )
  178. {
  179. PSECURITY_DESCRIPTOR psd = NULL;
  180. PSECURITY_DESCRIPTOR psd5 = NULL;
  181. PSECURITY_DESCRIPTOR updatedSD = NULL;
  182. DWORD dwBufferSize = 0;
  183. DWORD dwSize = 0;
  184. DWORD dwStatus = E_FAIL;
  185. #if DBG
  186. CL_ASSERT( ppPropertyList != NULL );
  187. CL_ASSERT( pdwPropertyListSize != NULL );
  188. ClRtlLogPrint( LOG_NOISE, "[API] ApiFixupNotifyCb: entering.\n" );
  189. #endif
  190. if ( pdwPropertyListSize && ppPropertyList )
  191. {
  192. *ppPropertyList = NULL;
  193. *pdwPropertyListSize = 0;
  194. //
  195. // try to get the W2K SD
  196. //
  197. dwStatus = DmQueryString( DmClusterParametersKey,
  198. CLUSREG_NAME_CLUS_SD,
  199. REG_BINARY,
  200. (LPWSTR *) &psd5,
  201. &dwBufferSize,
  202. &dwSize );
  203. if ( dwStatus != ERROR_SUCCESS )
  204. {
  205. //
  206. // not there or can't get it; try to get the NT4 SD
  207. //
  208. dwStatus = DmQueryString( DmClusterParametersKey,
  209. CLUSREG_NAME_CLUS_SECURITY,
  210. REG_BINARY,
  211. (LPWSTR *) &psd,
  212. &dwBufferSize,
  213. &dwSize );
  214. if ( dwStatus == ERROR_SUCCESS )
  215. {
  216. //
  217. // convert to W2K descriptor format and add in the Network
  218. // Service SID if necessary. updatedSD will be non-NULL if the
  219. // SID was added. The convert routine can fail and set psd5 to
  220. // NULL.
  221. //
  222. // The Service SID routine can be removed after the next major
  223. // release after Whistler/Windows Server 2003 is shipped.
  224. //
  225. psd5 = ClRtlConvertClusterSDToNT5Format( psd );
  226. dwStatus = ApipAddNetServiceSidToSD( psd5, &updatedSD );
  227. if ( dwStatus == ERROR_SUCCESS ) {
  228. if ( updatedSD != NULL ) {
  229. //
  230. // we've got a new SD so free the old one and point to
  231. // the new one
  232. //
  233. LocalFree( psd5 );
  234. psd5 = updatedSD;
  235. }
  236. } else {
  237. ClRtlLogPrint(LOG_CRITICAL,
  238. "[API] ApiFixupNotifyCb: Unable to add Network Service "
  239. "account to Cluster security descriptor. Error = %1!u!.\n",
  240. dwStatus );
  241. //
  242. // we did some work (hopefully). If the conversion failed,
  243. // psd5 will be null but that will be caught below.
  244. //
  245. dwStatus = ERROR_SUCCESS;
  246. }
  247. }
  248. }
  249. else
  250. {
  251. //
  252. // we have an W2K based SD; now see if the Network Service SID
  253. // needs to be added
  254. //
  255. dwStatus = ApipAddNetServiceSidToSD( psd5, &updatedSD );
  256. if ( dwStatus == ERROR_SUCCESS )
  257. {
  258. if ( updatedSD != NULL )
  259. {
  260. //
  261. // we've got a new SD so free the old one and point to
  262. // the new one
  263. //
  264. LocalFree( psd5 );
  265. psd5 = updatedSD;
  266. }
  267. }
  268. else {
  269. ClRtlLogPrint(LOG_CRITICAL,
  270. "[API] ApiFixupNotifyCb: Unable to add Network Service "
  271. "account to Cluster security descriptor. Error = %1!u!.\n",
  272. dwStatus );
  273. dwStatus = ERROR_SUCCESS;
  274. }
  275. }
  276. if ( dwStatus == ERROR_SUCCESS && psd5 != NULL )
  277. {
  278. //
  279. // build a property list describing the W2K security descriptor
  280. //
  281. *pdwPropertyListSize = sizeof( DWORD )
  282. + sizeof( CLUSPROP_PROPERTY_NAME )
  283. + ( ALIGN_CLUSPROP( ( lstrlenW( CLUSREG_NAME_CLUS_SD ) + 1 ) * sizeof( WCHAR ) ) )
  284. + sizeof( CLUSPROP_BINARY )
  285. + ALIGN_CLUSPROP( GetSecurityDescriptorLength( psd5 ) )
  286. + sizeof( CLUSPROP_SYNTAX );
  287. *ppPropertyList = LocalAlloc( LMEM_ZEROINIT, *pdwPropertyListSize );
  288. if ( *ppPropertyList != NULL )
  289. {
  290. CLUSPROP_BUFFER_HELPER props;
  291. props.pb = (BYTE *) *ppPropertyList;
  292. //
  293. // set the number of properties
  294. //
  295. props.pList->nPropertyCount = 1;
  296. props.pb += sizeof( props.pList->nPropertyCount ); // DWORD
  297. //
  298. // set the property name
  299. //
  300. props.pName->Syntax.dw = CLUSPROP_SYNTAX_NAME;
  301. props.pName->cbLength = ( lstrlenW( CLUSREG_NAME_CLUS_SD ) + 1 ) * sizeof( WCHAR );
  302. lstrcpyW( props.pName->sz, CLUSREG_NAME_CLUS_SD );
  303. props.pb += ( sizeof( CLUSPROP_PROPERTY_NAME )
  304. + ( ALIGN_CLUSPROP( ( lstrlenW( CLUSREG_NAME_CLUS_SD ) + 1 ) * sizeof( WCHAR ) ) ) );
  305. //
  306. // set the binary part of the property the SD...
  307. //
  308. props.pBinaryValue->Syntax.dw = CLUSPROP_SYNTAX_LIST_VALUE_BINARY;
  309. props.pBinaryValue->cbLength = GetSecurityDescriptorLength( psd5 );
  310. CopyMemory( props.pBinaryValue->rgb, psd5, GetSecurityDescriptorLength( psd5 ) );
  311. props.pb += sizeof(*props.pBinaryValue) + ALIGN_CLUSPROP( GetSecurityDescriptorLength( psd5 ) );
  312. //
  313. // Set an endmark.
  314. //
  315. props.pSyntax->dw = CLUSPROP_SYNTAX_ENDMARK;
  316. //
  317. // specify the registry key
  318. //
  319. *pszKeyName=(LPWSTR)LocalAlloc(LMEM_FIXED, (lstrlenW(L"Cluster") + 1) *sizeof(WCHAR));
  320. if( *pszKeyName == NULL ) {
  321. LocalFree( *ppPropertyList );
  322. *ppPropertyList = NULL;
  323. *pdwPropertyListSize = 0;
  324. dwStatus =GetLastError();
  325. }
  326. else
  327. {
  328. lstrcpyW(*pszKeyName,L"Cluster");
  329. }
  330. }
  331. else
  332. {
  333. dwStatus = GetLastError();
  334. ClRtlLogPrint(LOG_CRITICAL,
  335. "[API] ApiFixupNotifyCb: Unable to build property list "
  336. "for security descriptor update. status %1!u!\n",
  337. dwStatus);
  338. }
  339. }
  340. }
  341. else
  342. {
  343. #if DBG
  344. ClRtlLogPrint( LOG_CRITICAL, "[API] ApiFixupNotifyCb: Invalid parameters.\n" );
  345. #endif
  346. }
  347. LocalFree( psd5 );
  348. LocalFree( psd );
  349. return dwStatus;
  350. } // ApiFixupNotifyCb