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.

382 lines
9.5 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. strsd.c
  5. Abstract:
  6. This Module implements wrapper functions to convert from a specialized
  7. string representation of a security descriptor to the security descriptor
  8. itself, and the opposite function.
  9. Author:
  10. Environment:
  11. User Mode
  12. Revision History:
  13. --*/
  14. #include "headers.h"
  15. //#include <lmcons.h>
  16. //#include <secobj.h>
  17. //#include <netlib.h>
  18. //#include <ntsecapi.h>
  19. #include "sddl.h"
  20. #pragma hdrstop
  21. DWORD
  22. ScepGetSecurityInformation(
  23. IN PSECURITY_DESCRIPTOR pSD,
  24. OUT SECURITY_INFORMATION *pSeInfo
  25. );
  26. DWORD
  27. WINAPI
  28. ConvertTextSecurityDescriptor (
  29. IN PWSTR pwszTextSD,
  30. OUT PSECURITY_DESCRIPTOR *ppSD,
  31. OUT PULONG pcSDSize OPTIONAL,
  32. OUT PSECURITY_INFORMATION pSeInfo OPTIONAL
  33. )
  34. {
  35. DWORD rc=ERROR_SUCCESS;
  36. if ( NULL == pwszTextSD || NULL == ppSD ) {
  37. return(ERROR_INVALID_PARAMETER);
  38. }
  39. //
  40. // initialize output buffers
  41. //
  42. *ppSD = NULL;
  43. if ( pSeInfo ) {
  44. *pSeInfo = 0;
  45. }
  46. if ( pcSDSize ) {
  47. *pcSDSize = 0;
  48. }
  49. //
  50. // call SDDL convert apis
  51. //
  52. if ( ConvertStringSecurityDescriptorToSecurityDescriptorW(
  53. pwszTextSD,
  54. SDDL_REVISION_1,
  55. ppSD,
  56. pcSDSize
  57. ) ) {
  58. //
  59. // conversion succeeds
  60. //
  61. if ( pSeInfo && *ppSD ) {
  62. //
  63. // get the SeInfo
  64. //
  65. rc = ScepGetSecurityInformation(
  66. *ppSD,
  67. pSeInfo
  68. );
  69. if ( rc != ERROR_SUCCESS ) {
  70. LocalFree(*ppSD);
  71. *ppSD = NULL;
  72. if ( pcSDSize ) {
  73. *pcSDSize = 0;
  74. }
  75. }
  76. }
  77. } else {
  78. rc = GetLastError();
  79. }
  80. return(rc);
  81. }
  82. //
  83. // Replace any of the new SDDL acronyms with SIDs, so we can keep SDDL strings
  84. // compatible with older systems.
  85. //
  86. // Caller is responsible for free'ing the return string unless input string
  87. // is returned directly, when no replacement is performed.
  88. //
  89. // Returns:
  90. // ERROR_SUCCESS
  91. // ERROR_NOT_ENOUGH_MEMORY
  92. //
  93. DWORD
  94. ScepReplaceNewAcronymsInSDDL(
  95. IN LPWSTR pwszOldSDDL,
  96. OUT LPWSTR *ppwszNewSDDL,
  97. ULONG *pcchNewSDDL
  98. )
  99. {
  100. typedef struct _SDDLMapNode
  101. {
  102. PCWSTR pcwszAcronym;
  103. PCWSTR pcwszSid;
  104. DWORD cbSid; // pcwszSid byte size (excluding trailing zero), for optimization
  105. } SDDLMapNode;
  106. static const WCHAR pcwszSidAnonymous[] = L"S-1-5-7";
  107. static const WCHAR pcwszLocalService[] = L"S-1-5-19";
  108. static const WCHAR pcwszNetworkService[] = L"S-1-5-20";
  109. static const WCHAR pcwszRemoteDesktop[] = L"S-1-5-32-555";
  110. static const WCHAR pcwszNetConfigOps[] = L"S-1-5-32-556";
  111. static const WCHAR pcwszPerfmonUsers[] = L"S-1-5-32-558";
  112. static const WCHAR pcwszPerflogUser[] = L"S-1-5-32-559";
  113. static SDDLMapNode SDDLMap[7] = {
  114. { SDDL_ANONYMOUS, pcwszSidAnonymous, sizeof(pcwszSidAnonymous)-sizeof(WCHAR) },
  115. { SDDL_LOCAL_SERVICE, pcwszLocalService , sizeof(pcwszLocalService)-sizeof(WCHAR) },
  116. { SDDL_NETWORK_SERVICE, pcwszNetworkService,sizeof(pcwszNetworkService)-sizeof(WCHAR) },
  117. { SDDL_REMOTE_DESKTOP, pcwszRemoteDesktop ,sizeof(pcwszRemoteDesktop)-sizeof(WCHAR) },
  118. { SDDL_NETWORK_CONFIGURATION_OPS, pcwszNetConfigOps , sizeof(pcwszNetConfigOps)-sizeof(WCHAR) },
  119. { SDDL_PERFMON_USERS, pcwszPerfmonUsers , sizeof(pcwszPerfmonUsers)-sizeof(WCHAR) },
  120. { SDDL_PERFLOG_USERS, pcwszPerflogUser , sizeof(pcwszPerflogUser)-sizeof(WCHAR) },
  121. };
  122. static const DWORD dwSDDLMapSize = sizeof(SDDLMap)/sizeof(SDDLMapNode);
  123. DWORD dwCrtSDDL;
  124. WCHAR *pch, *pchNew;
  125. DWORD cbNewSDDL;
  126. bool fMatchFound = false;
  127. LPWSTR pwszNewSDDL = NULL;
  128. *ppwszNewSDDL = NULL;
  129. *pcchNewSDDL = 0;
  130. if(!pwszOldSDDL)
  131. {
  132. return ERROR_SUCCESS;
  133. }
  134. //
  135. // We make the following assumptions:
  136. // - all acronyms are two chars long
  137. // - they show up either after a ':' or a ';'
  138. //
  139. // First pass to calculate the size of new string
  140. //
  141. for(pch = pwszOldSDDL, cbNewSDDL = sizeof(WCHAR); // account for trailing zero
  142. *pch != L'\0';
  143. pch++, cbNewSDDL += sizeof(WCHAR))
  144. {
  145. //
  146. // Acronyms always show up only after a ':' or a ';'
  147. //
  148. if(pch > pwszOldSDDL &&
  149. (SDDL_SEPERATORC == *(pch - 1) ||
  150. SDDL_DELIMINATORC == *(pch - 1)))
  151. {
  152. for(dwCrtSDDL = 0; dwCrtSDDL < dwSDDLMapSize; dwCrtSDDL++)
  153. {
  154. if(*pch == SDDLMap[dwCrtSDDL].pcwszAcronym[0] &&
  155. *(pch + 1) == SDDLMap[dwCrtSDDL].pcwszAcronym[1])
  156. {
  157. //
  158. // match found
  159. //
  160. cbNewSDDL += SDDLMap[dwCrtSDDL].cbSid;
  161. pch++; // acronym is 2 chars, need to jump an extra char
  162. fMatchFound = true;
  163. break;
  164. }
  165. }
  166. }
  167. }
  168. //
  169. // optimization, if no replacement needed, immediately return old string
  170. //
  171. if(!fMatchFound)
  172. {
  173. *ppwszNewSDDL = pwszOldSDDL;
  174. return ERROR_SUCCESS;
  175. }
  176. pwszNewSDDL = (LPWSTR)LocalAlloc(0, cbNewSDDL);
  177. if(!pwszNewSDDL)
  178. {
  179. return ERROR_NOT_ENOUGH_MEMORY;
  180. }
  181. //
  182. // Second pass, copy from old string to new one, replacing new acronyms with their SIDs
  183. //
  184. for(pch = pwszOldSDDL, pchNew = pwszNewSDDL;
  185. *pch != L'\0';
  186. pch++, pchNew++)
  187. {
  188. fMatchFound = false;
  189. //
  190. // Acronyms always show up only after a ':' or a ';'
  191. //
  192. if(pch > pwszOldSDDL &&
  193. (SDDL_SEPERATORC == *(pch - 1) ||
  194. SDDL_DELIMINATORC == *(pch - 1)))
  195. {
  196. for(dwCrtSDDL = 0; dwCrtSDDL < dwSDDLMapSize; dwCrtSDDL++)
  197. {
  198. if(*pch == SDDLMap[dwCrtSDDL].pcwszAcronym[0] &&
  199. *(pch + 1) == SDDLMap[dwCrtSDDL].pcwszAcronym[1])
  200. {
  201. //
  202. // match found
  203. //
  204. fMatchFound = true;
  205. CopyMemory(pchNew, SDDLMap[dwCrtSDDL].pcwszSid, SDDLMap[dwCrtSDDL].cbSid);
  206. pch++; // acronym is 2 chars, need to jump an extra char
  207. pchNew += SDDLMap[dwCrtSDDL].cbSid/sizeof(WCHAR)-1; // minus one jumped in outer loop
  208. break;
  209. }
  210. }
  211. }
  212. if(!fMatchFound)
  213. {
  214. *pchNew = *pch;
  215. }
  216. }
  217. *pchNew = L'\0';
  218. *ppwszNewSDDL = pwszNewSDDL;
  219. *pcchNewSDDL = cbNewSDDL/sizeof(WCHAR);
  220. return ERROR_SUCCESS;
  221. }
  222. DWORD
  223. WINAPI
  224. ConvertSecurityDescriptorToText (
  225. IN PSECURITY_DESCRIPTOR pSD,
  226. IN SECURITY_INFORMATION SecurityInfo,
  227. OUT PWSTR *ppwszTextSD,
  228. OUT PULONG pcTextSize
  229. )
  230. {
  231. PWSTR pwszTempSD = NULL;
  232. ULONG cchSDSize;
  233. if (! ConvertSecurityDescriptorToStringSecurityDescriptorW(
  234. pSD,
  235. SDDL_REVISION_1,
  236. SecurityInfo,
  237. &pwszTempSD,
  238. pcTextSize
  239. ) )
  240. {
  241. return(GetLastError());
  242. }
  243. //
  244. // Replace any of the new SDDL acronyms with SIDs, so we can keep SDDL strings
  245. // compatible with older systems.
  246. //
  247. DWORD dwErr = ScepReplaceNewAcronymsInSDDL(pwszTempSD, ppwszTextSD, &cchSDSize);
  248. if(ERROR_SUCCESS != dwErr)
  249. {
  250. LocalFree(pwszTempSD);
  251. return dwErr;
  252. }
  253. if(*ppwszTextSD != pwszTempSD)
  254. {
  255. LocalFree(pwszTempSD);
  256. *pcTextSize = cchSDSize;
  257. }
  258. return ERROR_SUCCESS;
  259. }
  260. DWORD
  261. ScepGetSecurityInformation(
  262. IN PSECURITY_DESCRIPTOR pSD,
  263. OUT SECURITY_INFORMATION *pSeInfo
  264. )
  265. {
  266. PSID Owner = NULL, Group = NULL;
  267. BOOLEAN Defaulted;
  268. NTSTATUS Status;
  269. SECURITY_DESCRIPTOR_CONTROL ControlCode=0;
  270. ULONG Revision;
  271. if ( !pSeInfo ) {
  272. return(ERROR_INVALID_PARAMETER);
  273. }
  274. *pSeInfo = 0;
  275. if ( !pSD ) {
  276. return(ERROR_SUCCESS);
  277. }
  278. Status = RtlGetOwnerSecurityDescriptor( pSD, &Owner, &Defaulted );
  279. if ( NT_SUCCESS( Status ) ) {
  280. if ( Owner && !Defaulted ) {
  281. *pSeInfo |= OWNER_SECURITY_INFORMATION;
  282. }
  283. Status = RtlGetGroupSecurityDescriptor( pSD, &Group, &Defaulted );
  284. }
  285. if ( NT_SUCCESS( Status ) ) {
  286. if ( Group && !Defaulted ) {
  287. *pSeInfo |= GROUP_SECURITY_INFORMATION;
  288. }
  289. Status = RtlGetControlSecurityDescriptor ( pSD, &ControlCode, &Revision);
  290. }
  291. if ( NT_SUCCESS( Status ) ) {
  292. if ( ControlCode & SE_DACL_PRESENT ) {
  293. *pSeInfo |= DACL_SECURITY_INFORMATION;
  294. }
  295. if ( ControlCode & SE_SACL_PRESENT ) {
  296. *pSeInfo |= SACL_SECURITY_INFORMATION;
  297. }
  298. } else {
  299. *pSeInfo = 0;
  300. }
  301. return( RtlNtStatusToDosError(Status) );
  302. }