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.

466 lines
12 KiB

  1. /*********************************************************************/
  2. /** Copyright(c) 1995 Microsoft Corporation. **/
  3. /*********************************************************************/
  4. //***
  5. //
  6. // Filename: security.c
  7. //
  8. // Description: This module contains code that will create and delete the
  9. // security object. It will also contain access checking calls.
  10. //
  11. // History:
  12. // June 21,1995. NarenG Created original version.
  13. //
  14. // NOTE: ??? The lpdwAccessStatus parameter for AccessCheckAndAuditAlarm
  15. // returns junk. ???
  16. //
  17. #include "dimsvcp.h"
  18. #include <rpc.h>
  19. #include <ntseapi.h>
  20. #include <ntlsa.h>
  21. #include <ntsam.h>
  22. #include <ntsamp.h>
  23. typedef struct _DIM_SECURITY_OBJECT
  24. {
  25. LPWSTR lpwsObjectName;
  26. LPWSTR lpwsObjectType;
  27. GENERIC_MAPPING GenericMapping;
  28. PSECURITY_DESCRIPTOR pSecurityDescriptor;
  29. } DIM_SECURITY_OBJECT, PDIM_SECURITY_OBJECT;
  30. static DIM_SECURITY_OBJECT DimSecurityObject;
  31. #define DIMSVC_SECURITY_OBJECT TEXT("DimSvcAdminApi");
  32. #define DIMSVC_SECURITY_OBJECT_TYPE TEXT("Security");
  33. //**
  34. //
  35. // Call: DimSecObjCreate
  36. //
  37. // Returns: NO_ERROR - success
  38. // ERROR_NOT_ENOUGH_MEMORY
  39. // non-zero returns from security functions
  40. //
  41. // Description: This procedure will set up the security object that will
  42. // be used to check to see if an RPC client is an administrator
  43. // for the local machine.
  44. //
  45. DWORD
  46. DimSecObjCreate(
  47. VOID
  48. )
  49. {
  50. PSID pAdminSid = NULL;
  51. PSID pLocalSystemSid = NULL;
  52. PSID pServerOpSid = NULL;
  53. PACL pDacl = NULL;
  54. HANDLE hProcessToken = NULL;
  55. PULONG pSubAuthority;
  56. SID_IDENTIFIER_AUTHORITY SidIdentifierNtAuth = SECURITY_NT_AUTHORITY;
  57. SECURITY_DESCRIPTOR SecurityDescriptor;
  58. DWORD dwRetCode;
  59. DWORD cbDaclSize;
  60. //
  61. // Set up security object
  62. //
  63. DimSecurityObject.lpwsObjectName = DIMSVC_SECURITY_OBJECT;
  64. DimSecurityObject.lpwsObjectType = DIMSVC_SECURITY_OBJECT_TYPE;
  65. //
  66. // Generic mapping structure for the security object
  67. // All generic access types are allowed API access.
  68. //
  69. DimSecurityObject.GenericMapping.GenericRead = STANDARD_RIGHTS_READ |
  70. DIMSVC_ALL_ACCESS;
  71. DimSecurityObject.GenericMapping.GenericWrite = STANDARD_RIGHTS_WRITE |
  72. DIMSVC_ALL_ACCESS;
  73. DimSecurityObject.GenericMapping.GenericExecute =
  74. STANDARD_RIGHTS_EXECUTE |
  75. DIMSVC_ALL_ACCESS;
  76. DimSecurityObject.GenericMapping.GenericAll = DIMSVC_ALL_ACCESS;
  77. do
  78. {
  79. dwRetCode = NO_ERROR;
  80. //
  81. // Set up the SID for the admins that will be allowed to have
  82. // access. This SID will have 2 sub-authorities
  83. // SECURITY_BUILTIN_DOMAIN_RID and DOMAIN_ALIAS_ADMIN_RID.
  84. //
  85. pAdminSid = (PSID)LOCAL_ALLOC( LPTR, GetSidLengthRequired( 2 ) );
  86. if ( pAdminSid == NULL )
  87. {
  88. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  89. break;
  90. }
  91. if ( !InitializeSid( pAdminSid, &SidIdentifierNtAuth, 2 ) )
  92. {
  93. dwRetCode = GetLastError();
  94. break;
  95. }
  96. //
  97. // Set the sub-authorities
  98. //
  99. pSubAuthority = GetSidSubAuthority( pAdminSid, 0 );
  100. *pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
  101. pSubAuthority = GetSidSubAuthority( pAdminSid, 1 );
  102. *pSubAuthority = DOMAIN_ALIAS_RID_ADMINS;
  103. //
  104. // Create the server operators SID
  105. //
  106. pServerOpSid = (PSID)LOCAL_ALLOC( LPTR, GetSidLengthRequired( 2 ) );
  107. if ( pServerOpSid == NULL )
  108. {
  109. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  110. break;
  111. }
  112. if ( !InitializeSid( pServerOpSid, &SidIdentifierNtAuth, 2 ) )
  113. {
  114. dwRetCode = GetLastError();
  115. break;
  116. }
  117. //
  118. // Set the sub-authorities
  119. //
  120. pSubAuthority = GetSidSubAuthority( pServerOpSid, 0 );
  121. *pSubAuthority = SECURITY_BUILTIN_DOMAIN_RID;
  122. pSubAuthority = GetSidSubAuthority( pServerOpSid, 1 );
  123. *pSubAuthority = DOMAIN_ALIAS_RID_SYSTEM_OPS;
  124. //
  125. // Create the LocalSystemSid which will be the owner and the primary
  126. // group of the security object.
  127. //
  128. pLocalSystemSid = (PSID)LOCAL_ALLOC( LPTR, GetSidLengthRequired( 1 ) );
  129. if ( pLocalSystemSid == NULL )
  130. {
  131. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  132. break;
  133. }
  134. if ( !InitializeSid( pLocalSystemSid, &SidIdentifierNtAuth, 1 ) )
  135. {
  136. dwRetCode = GetLastError();
  137. break;
  138. }
  139. //
  140. // Set the sub-authorities
  141. //
  142. pSubAuthority = GetSidSubAuthority( pLocalSystemSid, 0 );
  143. *pSubAuthority = SECURITY_LOCAL_SYSTEM_RID;
  144. //
  145. // Set up the DACL that will allow admins with the above SID all access
  146. // It should be large enough to hold all ACEs.
  147. //
  148. cbDaclSize = sizeof(ACL) + ( sizeof(ACCESS_ALLOWED_ACE) * 2 ) +
  149. GetLengthSid(pAdminSid) + GetLengthSid(pServerOpSid);
  150. if ( (pDacl = (PACL)LOCAL_ALLOC( LPTR, cbDaclSize ) ) == NULL )
  151. {
  152. dwRetCode = ERROR_NOT_ENOUGH_MEMORY;
  153. break;
  154. }
  155. if ( !InitializeAcl( pDacl, cbDaclSize, ACL_REVISION2 ) )
  156. {
  157. dwRetCode = GetLastError();
  158. break;
  159. }
  160. //
  161. // Add the ACE to the DACL
  162. //
  163. if ( !AddAccessAllowedAce( pDacl,
  164. ACL_REVISION2,
  165. DIMSVC_ALL_ACCESS, // What the admin can do
  166. pAdminSid ))
  167. {
  168. dwRetCode = GetLastError();
  169. break;
  170. }
  171. if ( !AddAccessAllowedAce( pDacl,
  172. ACL_REVISION2,
  173. DIMSVC_ALL_ACCESS, // What the admin can do
  174. pServerOpSid ))
  175. {
  176. dwRetCode = GetLastError();
  177. break;
  178. }
  179. //
  180. // Create the security descriptor an put the DACL in it.
  181. //
  182. if ( !InitializeSecurityDescriptor( &SecurityDescriptor, 1 ))
  183. {
  184. dwRetCode = GetLastError();
  185. break;
  186. }
  187. if ( !SetSecurityDescriptorDacl( &SecurityDescriptor,
  188. TRUE,
  189. pDacl,
  190. FALSE ) )
  191. {
  192. dwRetCode = GetLastError();
  193. break;
  194. }
  195. //
  196. // Set owner for the descriptor
  197. //
  198. if ( !SetSecurityDescriptorOwner( &SecurityDescriptor,
  199. pLocalSystemSid,
  200. FALSE ) )
  201. {
  202. dwRetCode = GetLastError();
  203. break;
  204. }
  205. //
  206. // Set group for the descriptor
  207. //
  208. if ( !SetSecurityDescriptorGroup( &SecurityDescriptor,
  209. pLocalSystemSid,
  210. FALSE ) )
  211. {
  212. dwRetCode = GetLastError();
  213. break;
  214. }
  215. //
  216. // Get token for the current process
  217. //
  218. if ( !OpenProcessToken( GetCurrentProcess(),
  219. TOKEN_QUERY,
  220. &hProcessToken ))
  221. {
  222. dwRetCode = GetLastError();
  223. break;
  224. }
  225. //
  226. // Create a security object. This is really just a security descriptor
  227. // is self-relative form. This procedure will allocate memory for this
  228. // security descriptor and copy all in the information passed in. This
  229. // allows us to free all dynamic memory allocated.
  230. //
  231. if ( !CreatePrivateObjectSecurity(
  232. NULL,
  233. &SecurityDescriptor,
  234. &(DimSecurityObject.pSecurityDescriptor),
  235. FALSE,
  236. hProcessToken,
  237. &(DimSecurityObject.GenericMapping)
  238. ))
  239. dwRetCode = GetLastError();
  240. } while( FALSE );
  241. //
  242. // Free up the dynamic memory
  243. //
  244. if ( pLocalSystemSid != NULL )
  245. LOCAL_FREE( pLocalSystemSid );
  246. if ( pAdminSid != NULL )
  247. LOCAL_FREE( pAdminSid );
  248. if ( pServerOpSid != NULL )
  249. LOCAL_FREE( pServerOpSid );
  250. if ( pDacl != NULL )
  251. LOCAL_FREE( pDacl );
  252. if ( hProcessToken != NULL )
  253. CloseHandle( hProcessToken );
  254. return( dwRetCode );
  255. }
  256. //**
  257. //
  258. // Call: DimSecObjDelete
  259. //
  260. // Returns: NO_ERROR - success
  261. // non-zero returns from security functions
  262. //
  263. // Description: Will destroy a valid security descriptor.
  264. //
  265. DWORD
  266. DimSecObjDelete(
  267. VOID
  268. )
  269. {
  270. if ( !IsValidSecurityDescriptor( DimSecurityObject.pSecurityDescriptor))
  271. return( NO_ERROR );
  272. if (!DestroyPrivateObjectSecurity( &DimSecurityObject.pSecurityDescriptor))
  273. return( GetLastError() );
  274. return( NO_ERROR );
  275. }
  276. //**
  277. //
  278. // Call: DimSecObjAccessCheck
  279. //
  280. // Returns: NO_ERROR - success
  281. // non-zero returns from security functions
  282. //
  283. // Description: This procedure will first impersonate the client, then
  284. // check to see if the client has the desired access to the
  285. // security object. If he/she does then the AccessStatus
  286. // variable will be set to NO_ERROR otherwise it will be
  287. // set to ERROR_ACCESS_DENIED. It will the revert to self and
  288. // return.
  289. //
  290. DWORD
  291. DimSecObjAccessCheck(
  292. IN DWORD DesiredAccess,
  293. OUT LPDWORD lpdwAccessStatus
  294. )
  295. {
  296. DWORD dwRetCode;
  297. ACCESS_MASK GrantedAccess;
  298. BOOL fGenerateOnClose;
  299. //
  300. // Impersonate the client
  301. //
  302. dwRetCode = RpcImpersonateClient( NULL );
  303. if ( dwRetCode != RPC_S_OK )
  304. return( dwRetCode );
  305. dwRetCode = AccessCheckAndAuditAlarm(
  306. DIM_SERVICE_NAME,
  307. NULL,
  308. DimSecurityObject.lpwsObjectType,
  309. DimSecurityObject.lpwsObjectName,
  310. DimSecurityObject.pSecurityDescriptor,
  311. DesiredAccess,
  312. &(DimSecurityObject.GenericMapping),
  313. FALSE,
  314. &GrantedAccess,
  315. (LPBOOL)lpdwAccessStatus,
  316. &fGenerateOnClose
  317. );
  318. if ( !dwRetCode )
  319. {
  320. DWORD dwTmpRetCode = GetLastError();
  321. dwRetCode = RpcRevertToSelf();
  322. return( dwTmpRetCode );
  323. }
  324. dwRetCode = RpcRevertToSelf();
  325. if (dwRetCode != RPC_S_OK)
  326. return dwRetCode;
  327. //
  328. // Check if desired access == granted Access
  329. //
  330. if ( DesiredAccess != GrantedAccess )
  331. *lpdwAccessStatus = ERROR_ACCESS_DENIED;
  332. else
  333. *lpdwAccessStatus = NO_ERROR;
  334. return( NO_ERROR );
  335. }
  336. BOOL
  337. DimIsLocalService()
  338. {
  339. BOOL fIsLocalService = FALSE;
  340. RPC_STATUS rpcstatus;
  341. HANDLE CurrentThreadToken = NULL;
  342. BOOL fImpersonate = FALSE;
  343. DWORD retcode = ERROR_SUCCESS;
  344. SID sidLocalService = { 1, 1,
  345. SECURITY_NT_AUTHORITY,
  346. SECURITY_LOCAL_SERVICE_RID };
  347. rpcstatus = RpcImpersonateClient(NULL);
  348. if(RPC_S_OK != rpcstatus)
  349. {
  350. goto done;
  351. }
  352. fImpersonate = TRUE;
  353. retcode = NtOpenThreadToken(
  354. NtCurrentThread(),
  355. TOKEN_QUERY,
  356. TRUE,
  357. &CurrentThreadToken
  358. );
  359. if(retcode != ERROR_SUCCESS)
  360. {
  361. goto done;
  362. }
  363. if (!CheckTokenMembership( CurrentThreadToken,
  364. &sidLocalService, &fIsLocalService ))
  365. {
  366. fIsLocalService = FALSE;
  367. }
  368. done:
  369. if(fImpersonate)
  370. {
  371. retcode = RpcRevertToSelf();
  372. }
  373. if(NULL != CurrentThreadToken)
  374. {
  375. NtClose(CurrentThreadToken);
  376. }
  377. return fIsLocalService;
  378. }