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.

726 lines
19 KiB

  1. /*++
  2. Copyright (c) 1989 Microsoft Corporation
  3. Module Name:
  4. rtlassig.c
  5. Abstract:
  6. This Module implements many security rtl routines defined in ntseapi.h
  7. Author:
  8. Jim Kelly (JimK) 23-Mar-1990
  9. Robert Reichel (RobertRe) 1-Mar-1991
  10. Environment:
  11. Pure Runtime Library Routine
  12. Revision History:
  13. --*/
  14. #include "ntrtlp.h"
  15. #include "seopaque.h"
  16. #include "sertlp.h"
  17. #if defined(ALLOC_PRAGMA) && defined(NTOS_KERNEL_RUNTIME)
  18. #pragma alloc_text(PAGE,RtlSelfRelativeToAbsoluteSD)
  19. #pragma alloc_text(PAGE,RtlMakeSelfRelativeSD)
  20. #pragma alloc_text(PAGE,RtlpQuerySecurityDescriptor)
  21. #pragma alloc_text(PAGE,RtlAbsoluteToSelfRelativeSD)
  22. #pragma alloc_text(PAGE,RtlSelfRelativeToAbsoluteSD2)
  23. #endif
  24. ///////////////////////////////////////////////////////////////////////////////
  25. // //
  26. // Exported Procedures //
  27. // //
  28. ///////////////////////////////////////////////////////////////////////////////
  29. NTSTATUS
  30. RtlSelfRelativeToAbsoluteSD(
  31. IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  32. OUT PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  33. IN OUT PULONG AbsoluteSecurityDescriptorSize,
  34. IN OUT PACL Dacl,
  35. IN OUT PULONG DaclSize,
  36. IN OUT PACL Sacl,
  37. IN OUT PULONG SaclSize,
  38. IN OUT PSID Owner,
  39. IN OUT PULONG OwnerSize,
  40. IN OUT PSID PrimaryGroup,
  41. IN OUT PULONG PrimaryGroupSize
  42. )
  43. /*++
  44. Routine Description:
  45. Converts a security descriptor from self-relative format to absolute
  46. format
  47. Arguments:
  48. SecurityDescriptor - Supplies a pointer to a security descriptor in
  49. Self-Relative format
  50. AbsoluteSecurityDescriptor - A pointer to a buffer in which will be
  51. placed the main body of the Absolute format security descriptor.
  52. Dacl - Supplies a pointer to a buffer that will contain the Dacl of the
  53. output descriptor. This pointer will be referenced by, not copied
  54. into, the output descriptor.
  55. DaclSize - Supplies the size of the buffer pointed to by Dacl. In case
  56. of error, it will return the minimum size necessary to contain the
  57. Dacl.
  58. Sacl - Supplies a pointer to a buffer that will contain the Sacl of the
  59. output descriptor. This pointer will be referenced by, not copied
  60. into, the output descriptor.
  61. SaclSize - Supplies the size of the buffer pointed to by Sacl. In case
  62. of error, it will return the minimum size necessary to contain the
  63. Sacl.
  64. Owner - Supplies a pointer to a buffer that will contain the Owner of
  65. the output descriptor. This pointer will be referenced by, not
  66. copied into, the output descriptor.
  67. OwnerSize - Supplies the size of the buffer pointed to by Owner. In
  68. case of error, it will return the minimum size necessary to contain
  69. the Owner.
  70. PrimaryGroup - Supplies a pointer to a buffer that will contain the
  71. PrimaryGroup of the output descriptor. This pointer will be
  72. referenced by, not copied into, the output descriptor.
  73. PrimaryGroupSize - Supplies the size of the buffer pointed to by
  74. PrimaryGroup. In case of error, it will return the minimum size
  75. necessary to contain the PrimaryGroup.
  76. Return Value:
  77. STATUS_SUCCESS - Success
  78. STATUS_BUFFER_TOO_SMALL - One of the buffers passed was too small.
  79. STATUS_INVALID_OWNER - There was not a valid owner in the passed
  80. security descriptor.
  81. --*/
  82. {
  83. ULONG NewDaclSize;
  84. ULONG NewSaclSize;
  85. ULONG NewBodySize;
  86. ULONG NewOwnerSize;
  87. ULONG NewGroupSize;
  88. PSID NewOwner;
  89. PSID NewGroup;
  90. PACL NewDacl;
  91. PACL NewSacl;
  92. //
  93. // typecast security descriptors so we don't have to cast all over the place.
  94. //
  95. PISECURITY_DESCRIPTOR OutSD =
  96. AbsoluteSecurityDescriptor;
  97. PISECURITY_DESCRIPTOR InSD =
  98. (PISECURITY_DESCRIPTOR)SelfRelativeSecurityDescriptor;
  99. RTL_PAGED_CODE();
  100. if ( !RtlpAreControlBitsSet( InSD, SE_SELF_RELATIVE) ) {
  101. return( STATUS_BAD_DESCRIPTOR_FORMAT );
  102. }
  103. NewBodySize = sizeof(SECURITY_DESCRIPTOR);
  104. RtlpQuerySecurityDescriptor(
  105. InSD,
  106. &NewOwner,
  107. &NewOwnerSize,
  108. &NewGroup,
  109. &NewGroupSize,
  110. &NewDacl,
  111. &NewDaclSize,
  112. &NewSacl,
  113. &NewSaclSize
  114. );
  115. if ( (NewBodySize > *AbsoluteSecurityDescriptorSize) ||
  116. (NewOwnerSize > *OwnerSize ) ||
  117. (NewDaclSize > *DaclSize ) ||
  118. (NewSaclSize > *SaclSize ) ||
  119. (NewGroupSize > *PrimaryGroupSize ) ) {
  120. *AbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
  121. *PrimaryGroupSize = NewGroupSize;
  122. *OwnerSize = NewOwnerSize;
  123. *SaclSize = NewSaclSize;
  124. *DaclSize = NewDaclSize;
  125. return( STATUS_BUFFER_TOO_SMALL );
  126. }
  127. RtlMoveMemory( OutSD,
  128. InSD,
  129. sizeof(SECURITY_DESCRIPTOR_RELATIVE) );
  130. OutSD->Owner = NULL;
  131. OutSD->Group = NULL;
  132. OutSD->Sacl = NULL;
  133. OutSD->Dacl = NULL;
  134. RtlpClearControlBits( OutSD, SE_SELF_RELATIVE );
  135. if (NewOwner != NULL) {
  136. RtlMoveMemory( Owner, NewOwner, SeLengthSid( NewOwner ));
  137. OutSD->Owner = Owner;
  138. }
  139. if (NewGroup != NULL) {
  140. RtlMoveMemory( PrimaryGroup, NewGroup, SeLengthSid( NewGroup ));
  141. OutSD->Group = PrimaryGroup;
  142. }
  143. if (NewSacl != NULL) {
  144. RtlMoveMemory( Sacl, NewSacl, NewSacl->AclSize );
  145. OutSD->Sacl = Sacl;
  146. }
  147. if (NewDacl != NULL) {
  148. RtlMoveMemory( Dacl, NewDacl, NewDacl->AclSize );
  149. OutSD->Dacl = Dacl;
  150. }
  151. return( STATUS_SUCCESS );
  152. }
  153. NTSTATUS
  154. RtlMakeSelfRelativeSD(
  155. IN PSECURITY_DESCRIPTOR SecurityDescriptor,
  156. IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  157. IN OUT PULONG BufferLength
  158. )
  159. /*++
  160. Routine Description:
  161. Makes a copy of a security descriptor. The produced copy will be in self-relative
  162. form.
  163. The security descriptor to be copied may be in either absolute or self-relative
  164. form.
  165. Arguments:
  166. SecurityDescriptor - Pointer to a security descriptor. This descriptor will not
  167. be modified.
  168. SelfRelativeSecurityDescriptor - Pointer to a buffer that will contain
  169. the returned self-relative security descriptor.
  170. BufferLength - Supplies the length of the buffer. If the supplied
  171. buffer is not large enough to hold the self-relative security
  172. descriptor, an error will be returned, and this field will return
  173. the minimum size required.
  174. Return Value:
  175. STATUS_BUFFER_TOO_SMALL - The supplied buffer was too small to contain
  176. the resultant security descriptor.
  177. --*/
  178. {
  179. ULONG NewDaclSize;
  180. ULONG NewSaclSize;
  181. ULONG NewOwnerSize;
  182. ULONG NewGroupSize;
  183. ULONG AllocationSize;
  184. PSID NewOwner;
  185. PSID NewGroup;
  186. PACL NewDacl;
  187. PACL NewSacl;
  188. PCHAR Field;
  189. PCHAR Base;
  190. //
  191. // Convert security descriptors to new data type so we don't
  192. // have to cast all over the place.
  193. //
  194. PISECURITY_DESCRIPTOR_RELATIVE IResultantDescriptor =
  195. (PISECURITY_DESCRIPTOR_RELATIVE)SelfRelativeSecurityDescriptor;
  196. PISECURITY_DESCRIPTOR IPassedSecurityDescriptor =
  197. (PISECURITY_DESCRIPTOR)SecurityDescriptor;
  198. RtlpQuerySecurityDescriptor(
  199. IPassedSecurityDescriptor,
  200. &NewOwner,
  201. &NewOwnerSize,
  202. &NewGroup,
  203. &NewGroupSize,
  204. &NewDacl,
  205. &NewDaclSize,
  206. &NewSacl,
  207. &NewSaclSize
  208. );
  209. RTL_PAGED_CODE();
  210. AllocationSize = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
  211. NewOwnerSize +
  212. NewGroupSize +
  213. NewDaclSize +
  214. NewSaclSize ;
  215. if (AllocationSize > *BufferLength) {
  216. *BufferLength = AllocationSize;
  217. return( STATUS_BUFFER_TOO_SMALL );
  218. }
  219. RtlZeroMemory( IResultantDescriptor, AllocationSize );
  220. RtlCopyMemory( IResultantDescriptor,
  221. IPassedSecurityDescriptor,
  222. FIELD_OFFSET( SECURITY_DESCRIPTOR_RELATIVE, Owner ));
  223. Base = (PCHAR)(IResultantDescriptor);
  224. Field = Base + (ULONG)sizeof(SECURITY_DESCRIPTOR_RELATIVE);
  225. if (NewSaclSize > 0) {
  226. RtlCopyMemory( Field, NewSacl, NewSaclSize );
  227. IResultantDescriptor->Sacl = RtlPointerToOffset(Base,Field);
  228. Field += NewSaclSize;
  229. } else {
  230. IResultantDescriptor->Sacl = 0;
  231. }
  232. if (NewDaclSize > 0) {
  233. RtlCopyMemory( Field, NewDacl, NewDaclSize );
  234. IResultantDescriptor->Dacl = RtlPointerToOffset(Base,Field);
  235. Field += NewDaclSize;
  236. } else {
  237. IResultantDescriptor->Dacl = 0;
  238. }
  239. if (NewOwnerSize > 0) {
  240. RtlCopyMemory( Field, NewOwner, NewOwnerSize );
  241. IResultantDescriptor->Owner = RtlPointerToOffset(Base,Field);
  242. Field += NewOwnerSize;
  243. }
  244. if (NewGroupSize > 0) {
  245. RtlCopyMemory( Field, NewGroup, NewGroupSize );
  246. IResultantDescriptor->Group = RtlPointerToOffset(Base,Field);
  247. }
  248. RtlpSetControlBits( IResultantDescriptor, SE_SELF_RELATIVE );
  249. return( STATUS_SUCCESS );
  250. }
  251. NTSTATUS
  252. RtlAbsoluteToSelfRelativeSD(
  253. IN PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
  254. IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
  255. IN OUT PULONG BufferLength
  256. )
  257. /*++
  258. Routine Description:
  259. Converts a security descriptor in absolute form to one in self-relative
  260. form.
  261. Arguments:
  262. AbsoluteSecurityDescriptor - Pointer to an absolute format security
  263. descriptor. This descriptor will not be modified.
  264. SelfRelativeSecurityDescriptor - Pointer to a buffer that will contain
  265. the returned self-relative security descriptor.
  266. BufferLength - Supplies the length of the buffer. If the supplied
  267. buffer is not large enough to hold the self-relative security
  268. descriptor, an error will be returned, and this field will return
  269. the minimum size required.
  270. Return Value:
  271. STATUS_BUFFER_TOO_SMALL - The supplied buffer was too small to contain
  272. the resultant security descriptor.
  273. STATUS_BAD_DESCRIPTOR_FORMAT - The supplied security descriptor was not
  274. in absolute form.
  275. --*/
  276. {
  277. NTSTATUS NtStatus;
  278. PISECURITY_DESCRIPTOR IAbsoluteSecurityDescriptor =
  279. (PISECURITY_DESCRIPTOR)AbsoluteSecurityDescriptor;
  280. RTL_PAGED_CODE();
  281. //
  282. // Make sure the passed SD is absolute format, and then call
  283. // RtlMakeSelfRelativeSD() to do all the work.
  284. //
  285. if ( RtlpAreControlBitsSet( IAbsoluteSecurityDescriptor, SE_SELF_RELATIVE) ) {
  286. return( STATUS_BAD_DESCRIPTOR_FORMAT );
  287. }
  288. NtStatus = RtlMakeSelfRelativeSD(
  289. AbsoluteSecurityDescriptor,
  290. SelfRelativeSecurityDescriptor,
  291. BufferLength
  292. );
  293. return( NtStatus );
  294. }
  295. VOID
  296. RtlpQuerySecurityDescriptor(
  297. IN PISECURITY_DESCRIPTOR SecurityDescriptor,
  298. OUT PSID *Owner,
  299. OUT PULONG OwnerSize,
  300. OUT PSID *PrimaryGroup,
  301. OUT PULONG PrimaryGroupSize,
  302. OUT PACL *Dacl,
  303. OUT PULONG DaclSize,
  304. OUT PACL *Sacl,
  305. OUT PULONG SaclSize
  306. )
  307. /*++
  308. Routine Description:
  309. Returns the pieces of a security descriptor structure.
  310. Arguments:
  311. SecurityDescriptor - Provides the security descriptor of interest.
  312. Owner - Returns a pointer to the owner information contained in the
  313. security descriptor.
  314. OwnerSize - Returns the size of the owner information.
  315. PrimaryGroup - Returns a pointer to the primary group information.
  316. PrimaryGroupSize - Returns the size of the primary group information.
  317. Dacl - Returns a pointer to the Dacl.
  318. DaclSize - Returns the size of the Dacl.
  319. Sacl - Returns a pointer to the Sacl.
  320. SaclSize - Returns the size of the Sacl.
  321. Return Value:
  322. None.
  323. --*/
  324. {
  325. RTL_PAGED_CODE();
  326. *Owner = RtlpOwnerAddrSecurityDescriptor( SecurityDescriptor );
  327. if (*Owner != NULL) {
  328. *OwnerSize = LongAlignSize(SeLengthSid(*Owner));
  329. } else {
  330. *OwnerSize = 0;
  331. }
  332. *Dacl = RtlpDaclAddrSecurityDescriptor ( SecurityDescriptor );
  333. if (*Dacl !=NULL) {
  334. *DaclSize = LongAlignSize((*Dacl)->AclSize);
  335. } else {
  336. *DaclSize = 0;
  337. }
  338. *PrimaryGroup = RtlpGroupAddrSecurityDescriptor( SecurityDescriptor );
  339. if (*PrimaryGroup != NULL) {
  340. *PrimaryGroupSize = LongAlignSize(SeLengthSid(*PrimaryGroup));
  341. } else {
  342. *PrimaryGroupSize = 0;
  343. }
  344. *Sacl = RtlpSaclAddrSecurityDescriptor( SecurityDescriptor );
  345. if (*Sacl != NULL) {
  346. *SaclSize = LongAlignSize((*Sacl)->AclSize);
  347. } else {
  348. *SaclSize = 0;
  349. }
  350. }
  351. NTSTATUS
  352. RtlSelfRelativeToAbsoluteSD2(
  353. IN OUT PSECURITY_DESCRIPTOR pSelfRelativeSecurityDescriptor,
  354. IN OUT PULONG pBufferSize
  355. )
  356. /*++
  357. Routine Description:
  358. Converts a security descriptor from self-relative format to absolute
  359. format using the memory allocated for the SelfRelativeSecurityDescriptor
  360. Arguments:
  361. pSecurityDescriptor - Supplies a pointer to a security descriptor in
  362. Self-Relative format. If success, we return a absolute security
  363. descriptor where this pointer pointings.
  364. pBufferSize - Supplies a pointer to the size of the
  365. buffer.
  366. Return Value:
  367. STATUS_SUCCESS - Success
  368. STATUS_BAD_DESCRIPTOR_FORMAT - The passed descriptor is not a self-relative
  369. security descriptor.
  370. STATUS_BUFFER_TOO_SMALL - The passed buffer is too small.
  371. STATUS_INVALID_OWNER - There was not a valid owner in the passed
  372. security descriptor.
  373. Notes: Despite some attempts to make this code as portable as possible and the
  374. utilization of C_ASSERT or ASSERT to detect the respect of these assumptions,
  375. this code is still making several assumptions about the format of the absolute
  376. and self-relative descriptors and their relationships: in terms of packing,
  377. fields definitions and locations in their respective structures.
  378. In particular, this code assumes that the only differences are due to differences
  379. in the types of the structure members and in the behaviour of the security descriptor
  380. query API.
  381. At this time, the only structure members that get read/updated are Owner, Group,
  382. Dacl and Sacl. If more members are added or displaced in the definitions of these
  383. structures, this code may have to be modified.
  384. --*/
  385. {
  386. ULONG_PTR ptr;
  387. PSID owner;
  388. PSID group;
  389. PACL dacl;
  390. PACL sacl;
  391. ULONG daclSize;
  392. ULONG saclSize;
  393. ULONG newBodySize;
  394. ULONG ownerSize;
  395. ULONG groupSize;
  396. ULONG newBufferSize;
  397. LONG deltaSize;
  398. //
  399. // Typecast security descriptors so we don't have to cast all over the place.
  400. //
  401. PISECURITY_DESCRIPTOR psd = (PISECURITY_DESCRIPTOR) pSelfRelativeSecurityDescriptor;
  402. PISECURITY_DESCRIPTOR_RELATIVE psdr = (PISECURITY_DESCRIPTOR_RELATIVE)pSelfRelativeSecurityDescriptor;
  403. //
  404. // This code uses several assumptions about the absolute and self-relative formats of
  405. // security descriptors and the way they are packing in memory.
  406. // See Routine Description Notes.
  407. //
  408. C_ASSERT( sizeof( SECURITY_DESCRIPTOR ) >= sizeof( SECURITY_DESCRIPTOR_RELATIVE ) );
  409. C_ASSERT( sizeof( psd->Control ) == sizeof( psdr->Control ) );
  410. C_ASSERT( FIELD_OFFSET( SECURITY_DESCRIPTOR, Control ) == FIELD_OFFSET( SECURITY_DESCRIPTOR_RELATIVE, Control ) );
  411. RTL_PAGED_CODE();
  412. //
  413. // Parameters check point
  414. //
  415. if ( psd == (PISECURITY_DESCRIPTOR)0 ) {
  416. return( STATUS_INVALID_PARAMETER_1 );
  417. }
  418. if ( pBufferSize == (PULONG)0 ) {
  419. return( STATUS_INVALID_PARAMETER_2 );
  420. }
  421. //
  422. // If the passed security descriptor is not self-relative, we return
  423. // an format error.
  424. //
  425. if ( !RtlpAreControlBitsSet( psd, SE_SELF_RELATIVE) ) {
  426. return( STATUS_BAD_DESCRIPTOR_FORMAT );
  427. }
  428. //
  429. // Update local variables by querying the self-relative descriptor.
  430. //
  431. // Note that the returned size values are long-aligned.
  432. //
  433. RtlpQuerySecurityDescriptor(
  434. psd,
  435. &owner,
  436. &ownerSize,
  437. &group,
  438. &groupSize,
  439. &dacl,
  440. &daclSize,
  441. &sacl,
  442. &saclSize
  443. );
  444. //
  445. // Identical formats check:
  446. //
  447. //
  448. // Determine the delta in size between the two formats of security descriptors
  449. //
  450. deltaSize = sizeof( SECURITY_DESCRIPTOR ) - sizeof( SECURITY_DESCRIPTOR_RELATIVE );
  451. //
  452. // If identical format:
  453. // - clear the SELF_RELATIVE flag
  454. // - update absolute descriptor members
  455. // - return SUCCESS.
  456. //
  457. if ( deltaSize == 0 ) {
  458. RtlpClearControlBits( psd, SE_SELF_RELATIVE );
  459. //
  460. // Only the following fields are updated.
  461. //
  462. ASSERT( sizeof( psd->Owner ) == sizeof( psdr->Owner ) );
  463. ASSERT( sizeof( psd->Group ) == sizeof( psdr->Group ) );
  464. ASSERT( sizeof( psd->Sacl ) == sizeof( psdr->Sacl ) );
  465. ASSERT( sizeof( psd->Dacl ) == sizeof( psdr->Dacl ) );
  466. psd->Owner = owner;
  467. psd->Group = group;
  468. psd->Sacl = sacl;
  469. psd->Dacl = dacl;
  470. return( STATUS_SUCCESS );
  471. }
  472. //
  473. // Determine the required size for the absolute format:
  474. //
  475. #define ULONG_PTR_SDEND( _Adr ) ( (ULONG_PTR)(_Adr) + (ULONG_PTR)(_Adr##Size) )
  476. ptr = owner > group ? ULONG_PTR_SDEND( owner ) : ULONG_PTR_SDEND( group );
  477. ptr = ptr > (ULONG_PTR)dacl ? ptr : ULONG_PTR_SDEND( dacl );
  478. ptr = ptr > (ULONG_PTR)sacl ? ptr : ULONG_PTR_SDEND( sacl );
  479. newBufferSize = sizeof( SECURITY_DESCRIPTOR );
  480. if ( ptr ) {
  481. #define ULONG_ROUND_UP( x, y ) ((ULONG)(x) + ((y)-1) & ~((y)-1))
  482. newBufferSize += ULONG_ROUND_UP( (ULONG_PTR)ptr - (ULONG_PTR)(psdr + 1), sizeof(PVOID) );
  483. }
  484. //
  485. // If the specified buffer size is not big enough, let the caller know abour
  486. // the minimum size and return STATUS_BUFFER_TOO_SMALL.
  487. //
  488. if ( newBufferSize > *pBufferSize ) {
  489. *pBufferSize = newBufferSize;
  490. return( STATUS_BUFFER_TOO_SMALL );
  491. }
  492. //
  493. // Update absolute security descriptor:
  494. //
  495. //
  496. // Move the members of self-relative security descriptor in their
  497. // absolute format locations.
  498. //
  499. if ( ptr ) {
  500. RtlMoveMemory( (PVOID)(psd + 1), (PVOID)(psdr + 1), newBufferSize - sizeof( SECURITY_DESCRIPTOR) );
  501. }
  502. //
  503. // Clear the self-relative flag
  504. //
  505. RtlpClearControlBits( psd, SE_SELF_RELATIVE );
  506. //
  507. // Only the following fields are updated.
  508. //
  509. psd->Owner = (PSID)( owner ? (ULONG_PTR)owner + deltaSize : 0 );
  510. psd->Group = (PSID)( group ? (ULONG_PTR)group + deltaSize : 0 );
  511. psd->Sacl = (PACL)( sacl ? (ULONG_PTR)sacl + deltaSize : 0 );
  512. psd->Dacl = (PACL)( dacl ? (ULONG_PTR)dacl + deltaSize : 0 );
  513. return( STATUS_SUCCESS );
  514. } // RtlSelfRelativeToAbsoluteSD2()