Source code of Windows XP (NT5)
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.

412 lines
10 KiB

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