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.

684 lines
16 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. adl.h
  5. Abstract:
  6. The header file for the ADL language parser / printer
  7. Author:
  8. t-eugenz - August 2000
  9. Environment:
  10. User mode only.
  11. Revision History:
  12. Created - August 2000
  13. --*/
  14. #include "pch.h"
  15. #include "adlinterface.h"
  16. #include <string>
  17. #include <list>
  18. #include <stack>
  19. #include <map>
  20. using namespace std;
  21. //
  22. // Forward declarations
  23. //
  24. class AdlToken;
  25. class AdlLexer;
  26. class AdlTree;
  27. class AdlStatement;
  28. struct AdlCompareStruct
  29. /*++
  30. Struct: AdlCompareStruct
  31. Description:
  32. STL requires custom key comparisons for containers to be supplied in
  33. such a struct.
  34. --*/
  35. {
  36. bool operator()(IN const PSID pSid1,
  37. IN const PSID pSid2) const;
  38. bool operator()(IN const WCHAR * sz1,
  39. IN const WCHAR * sz2) const;
  40. };
  41. class AdlStatement
  42. /*++
  43. Class: AdlStatement
  44. Description:
  45. This class contains a description of a DACL on an object, using the ADL
  46. language. An instance of this class can be constructed from an ACL or
  47. from a string statement in the ADL language. Once constructed, an ACL
  48. or a string statement in the ADL language can be output by an instance
  49. of this class.
  50. Base Classes: none
  51. Friend Classes: AdlLexer
  52. --*/
  53. {
  54. //
  55. // Friend classes necessary to access the garbage collection functionality,
  56. // and for parsing ADL
  57. //
  58. friend class AdlLexer;
  59. public:
  60. //
  61. // Initializes the AdlStatement
  62. //
  63. AdlStatement(IN const PADL_PARSER_CONTROL pControl)
  64. { _bReady = FALSE; _tokError = NULL; _pControl = pControl;
  65. ValidateParserControl(); }
  66. //
  67. // Destructor, frees tokens created by this and other classes
  68. //
  69. ~AdlStatement();
  70. //
  71. // Reads in the ADL statement in the input string
  72. //
  73. void ReadFromString(IN const WCHAR *szInput);
  74. //
  75. // Creates an ADL statement equivalent to the given DACL
  76. //
  77. void ReadFromDacl(IN const PACL pDacl);
  78. //
  79. // Prints the AdlStatement as a statement in the ADL language,
  80. // appending it to the allocated STL wstring pSz
  81. //
  82. void WriteToString(OUT wstring *pSz);
  83. //
  84. // Writes the ADL statement to a new DACL and returns the pointer to
  85. // the new DACL in *ppDacl
  86. //
  87. void WriteToDacl(OUT PACL *ppDacl);
  88. //
  89. // Gets the error string token, if any (depends on error code)
  90. //
  91. const AdlToken * GetErrorToken()
  92. { return _tokError; }
  93. //
  94. // This should be used to free any memory allocated by this class
  95. //
  96. static void FreeMemory(PVOID pMem)
  97. { delete[] (PBYTE) pMem; }
  98. public:
  99. //
  100. // AdlStatement throws exceptions of this type on any error
  101. // Some of the errors will make the offending token available
  102. // through GetErrorToken()
  103. //
  104. typedef enum
  105. {
  106. ERROR_NO_ERROR = 0,
  107. //
  108. // Internal errors which shoul not occur
  109. //
  110. ERROR_FATAL_LEXER_ERROR,
  111. ERROR_FATAL_PARSER_ERROR,
  112. ERROR_FATAL_ACL_CONVERT_ERROR,
  113. //
  114. // Errors due to the system the code is running on
  115. //
  116. ERROR_OUT_OF_MEMORY,
  117. ERROR_ACL_API_FAILED,
  118. //
  119. // Possible error due to network problems
  120. //
  121. ERROR_LSA_FAILED,
  122. //
  123. // If the ADL_PARSER_CONTROL is invalid, this is thrown
  124. //
  125. ERROR_INVALID_PARSER_CONTROL,
  126. //
  127. // Unknown ACE type encountered in DACL, no token supplied
  128. //
  129. ERROR_UNKNOWN_ACE_TYPE,
  130. //
  131. // User tried to specify impersonation as "user1 as user2"
  132. // Not currently supported
  133. //
  134. ERROR_IMPERSONATION_UNSUPPORTED,
  135. //
  136. // User error, no token supplied, quote with no closing quote
  137. //
  138. ERROR_UNTERMINATED_STRING,
  139. //
  140. // The user's statement was not in the ADL language (grammar error)
  141. // For this error, the offending token is supplied, though
  142. // the mistake may have happened before that token and was
  143. // accepted by the grammar
  144. //
  145. ERROR_NOT_IN_LANGUAGE,
  146. //
  147. // User input-related errors
  148. // For these errors, the offending token is supplied
  149. //
  150. //
  151. // User was not found by LSA lookup
  152. //
  153. ERROR_UNKNOWN_USER,
  154. //
  155. // Permission string was not one of those listed in the parser control
  156. //
  157. ERROR_UNKNOWN_PERMISSION,
  158. //
  159. // Username contained invalid characters
  160. //
  161. ERROR_INVALID_USERNAME,
  162. //
  163. // Domain name contained invalid characters
  164. //
  165. ERROR_INVALID_DOMAIN,
  166. //
  167. // Invalid inheritance specified. Not currently used, since
  168. // object type errors are caught at the grammar level
  169. //
  170. ERROR_INVALID_OBJECT,
  171. //
  172. // Other errors with no token supplied
  173. //
  174. //
  175. // A SID in an ACE was not found and mapped to a name by the LSA lookup
  176. //
  177. ERROR_UNKNOWN_SID,
  178. //
  179. // An access mask was encountered in an ACE that could not be
  180. // expressed by the user-specified permission mapping
  181. //
  182. ERROR_UNKNOWN_ACCESS_MASK,
  183. //
  184. // The ACL cannot be expressed in ADL. This means that, for some access
  185. // mask bit and set of inheritance flags, there exists a DENY ACE in the
  186. // ACL with the given bit set in its mask and with the given flags such
  187. // that either there is no ALLOW ACE which also has this bit set and has
  188. // the same inheritance flags further down in the ACL, or another
  189. // ACE with DIFFERENT inheritance flags and the same bit set follows
  190. // this DENY ace. For more information, see the ADL conversion
  191. // algorithm.
  192. //
  193. ERROR_INEXPRESSIBLE_ACL,
  194. //
  195. // User attempted an output operation on AdlStatement without
  196. // first successfully inputting data from either a string or an ACL
  197. //
  198. ERROR_NOT_INITIALIZED
  199. } ADL_ERROR_TYPE;
  200. private:
  201. //
  202. // Internal representation of an ADL statement
  203. //
  204. list<AdlTree *> _lTree; // A set of parsed ADL statements, as AdlTree's
  205. list<AdlTree *>::iterator _iter; // Iterator for the above set
  206. stack<AdlToken *> _AllocatedTokens; // Tokens to be garbage collected
  207. PADL_PARSER_CONTROL _pControl;
  208. const AdlToken * _tokError;
  209. BOOL _bReady;
  210. private:
  211. //
  212. // Goes through the list of AdlTrees, collects a list of all usernames
  213. // used, and makes a single LSA call to look up all SIDs, inserting the
  214. // PSIDs into the map by the (unique) token pointer.
  215. //
  216. void ConvertNamesToSids(
  217. IN OUT map<const AdlToken *, PSID> * mapTokSid
  218. );
  219. //
  220. // Goes throw the DACL, collects a lost of all SIDs used, and makes a
  221. // single LSA call to look up all names, inserting the looked up
  222. // names into the provided map as AdlTokens, which are garbage-
  223. // collected when the AdlStatement is deleted
  224. //
  225. void ConvertSidsToNames(
  226. IN const PACL pDacl,
  227. IN OUT map<const PSID, const AdlToken *> * mapSidsNames
  228. );
  229. //
  230. // Reads a DACL, and constructs an ADL statement from it
  231. //
  232. void ConvertFromDacl(
  233. IN const PACL pDacl
  234. );
  235. //
  236. // Returns the access mask corresponding to the given right name
  237. //
  238. ACCESS_MASK MapTokenToMask(
  239. IN const AdlToken * tokPermission
  240. );
  241. //
  242. // Fills in a list ofr const WCHAR *'s matching the passed in access
  243. // mask, using the preference order given in the grammar
  244. //
  245. void MapMaskToStrings(IN ACCESS_MASK amMask,
  246. IN OUT list<WCHAR *> *pList
  247. ) const;
  248. //
  249. // Cleans up all of the AdlTrees and all tokens
  250. //
  251. void Cleanup();
  252. //
  253. // Parses a string in the ADL language
  254. // This function is generated by YACC from the ADL grammar
  255. //
  256. int ParseAdl(IN const WCHAR *szInput);
  257. //
  258. // Returns the current AdlTree, this is used by the ADL parser to create
  259. // an ADL statement, one tree at a time
  260. //
  261. AdlTree * Cur();
  262. //
  263. // Creates a new AdlTree and pushes it onto the top of the list
  264. // Used by the ADL parser once the end of a single ADL statement is reached
  265. //
  266. void Next();
  267. //
  268. // If the last added AdlTree is empty, remove it
  269. // Used by the ADL parser, since it adds an AdlTree at the end
  270. // of a production instead of the beginning (YACC problem)
  271. //
  272. void PopEmpty();
  273. //
  274. // This is used to validate passed in ADL_PARSER_CONTROL structure
  275. // referenced by this class
  276. //
  277. void ValidateParserControl();
  278. protected:
  279. //
  280. // Used to set the error-causing string
  281. //
  282. void SetErrorToken(const AdlToken *tokError)
  283. { _tokError = tokError; }
  284. //
  285. // Adds a token pointer to be deleted when the AdlStatement is deleted
  286. //
  287. void AddToken(IN AdlToken *tok);
  288. };
  289. class AdlLexer
  290. /*++
  291. Class: AdlLexer
  292. Description:
  293. This class is the lexer for the ADL language. It allows the ADL parser
  294. to retrieve tokens from an input string, one token at a time.
  295. Base Classes: none
  296. Friend Classes: none
  297. --*/
  298. {
  299. private:
  300. const WCHAR *_input; // The input string
  301. DWORD _position; // Current position in the input string
  302. DWORD _start; // Start of current token in the buffer
  303. DWORD _tokCount; // Number of tokens so far retrieved
  304. //
  305. // Pointer to the AdlStatement instance which created this AdlLexer
  306. // instance, for token garbage collection
  307. //
  308. AdlStatement *_adlStat;
  309. //
  310. // Pointer to the ADL_LANGUAGE_SPEC structure defining the language to
  311. // be parsed
  312. //
  313. PADL_LANGUAGE_SPEC _pLang;
  314. //
  315. // Mapping of special characters to character codes
  316. // Special characters are assigned codes above WCHAR max
  317. //
  318. map<WCHAR, DWORD> _mapCharCode;
  319. //
  320. // Mapping from wstring to identify special tokens
  321. //
  322. map<const WCHAR *, DWORD, AdlCompareStruct> _mapStringToken;
  323. //
  324. // Iterators used by NextToken, this way they are only allocated once
  325. //
  326. map<WCHAR, DWORD>::iterator _iterEnd;
  327. map<WCHAR, DWORD>::iterator _iter;
  328. public:
  329. //
  330. // Constructs a lexer for an input string
  331. // NextToken() can then be called
  332. //
  333. AdlLexer(IN const WCHAR *input,
  334. IN OUT AdlStatement *adlStat,
  335. IN const PADL_LANGUAGE_SPEC pLang);
  336. //
  337. // Retrieves the next token from the input string
  338. // Returns 0 for the token type when the end of the string
  339. // is reached, as the YACC-generated parser requires.
  340. // A pointer to a new token instance containing the token
  341. // string, row, col, etc, is stored in *value
  342. //
  343. DWORD NextToken(OUT AdlToken **value);
  344. };
  345. class AdlToken
  346. /*++
  347. Class: AdlToken
  348. Description:
  349. This class contains the relevant information for a token. It is used in
  350. parsing ADL.
  351. Base Classes: none
  352. Friend Classes: none
  353. --*/
  354. {
  355. private:
  356. DWORD _begin; // Start position in the buffer
  357. DWORD _end; // End position in the buffer
  358. wstring _value; // String value of token
  359. //
  360. // This allows for collapsing multi-part tokens
  361. // such as [email protected] into a single
  362. // token by the parser after the individual subparts
  363. // are verified
  364. //
  365. wstring _optValue;
  366. public:
  367. //
  368. // Constructor for a single-part token
  369. //
  370. AdlToken(IN const WCHAR *value,
  371. IN DWORD begin,
  372. IN DWORD end
  373. )
  374. { _value.append(value); _begin = begin; _end = end; }
  375. //
  376. // Constructor for a multi-part token
  377. //
  378. AdlToken(IN const WCHAR *value,
  379. IN const WCHAR *optValue,
  380. IN DWORD begin,
  381. IN DWORD end
  382. )
  383. { _value.append(value); _optValue.append(optValue);
  384. _begin = begin; _end = end; }
  385. //
  386. // Accessors
  387. //
  388. DWORD GetStart() const
  389. { return _begin; }
  390. DWORD GetEnd() const
  391. { return _end; }
  392. const WCHAR * GetValue() const
  393. { return _value.c_str(); }
  394. const WCHAR * GetOptValue() const
  395. { return (_optValue.empty() ? NULL : _optValue.c_str()); }
  396. };
  397. class AdlTree
  398. /*++
  399. Class: AdlTree
  400. Description:
  401. This class contains the parsed information from a single ADL
  402. substatement, still in string form. The inheritance information
  403. is converted to a mask. The names contained are not necessarily
  404. valid however.
  405. Base Classes: none
  406. Friend Classes: none
  407. --*/
  408. {
  409. private:
  410. list<const AdlToken *> _lpTokPrincipals;
  411. list<const AdlToken *> _lpTokExPrincipals;
  412. list<const AdlToken *> _lpTokPermissions;
  413. DWORD _dwInheritFlags;
  414. public:
  415. //
  416. // Default to inherit-only, since "this object" must be specified
  417. // to clear that bit
  418. //
  419. AdlTree()
  420. { _dwInheritFlags = INHERIT_ONLY_ACE; }
  421. //
  422. // This outputs the ADL statement to stdout
  423. // Later to go to a string
  424. //
  425. void PrintAdl(wstring *pSz, PADL_PARSER_CONTROL pControl);
  426. //
  427. // Accessors/mutators
  428. // The Add*/Set* mutators are used by the YACC-generated AdlParse()
  429. // function to store information as it is parsed, adding the tokens
  430. // to the correct places in the AdlTree
  431. //
  432. void AddPrincipal(IN const AdlToken * pTokPrincipal)
  433. { _lpTokPrincipals.push_back(pTokPrincipal); }
  434. void AddExPrincipal(IN const AdlToken * pTokPrincipal)
  435. { _lpTokExPrincipals.push_back(pTokPrincipal); }
  436. void AddPermission(IN const AdlToken * pTokPermission)
  437. { _lpTokPermissions.push_back(pTokPermission); }
  438. //
  439. // Accessors used by AdlStat conversion functions
  440. //
  441. list<const AdlToken *> * GetPrincipals()
  442. { return &_lpTokPrincipals; }
  443. list<const AdlToken *> * GetExPrincipals()
  444. { return &_lpTokExPrincipals; }
  445. list<const AdlToken *> * GetPermissions()
  446. { return &_lpTokPermissions; }
  447. //
  448. // Set/unset/get inheritance flags
  449. //
  450. void SetFlags(DWORD dwFlags)
  451. { _dwInheritFlags |= dwFlags; }
  452. void UnsetFlags(DWORD dwFlags)
  453. { _dwInheritFlags &= (~dwFlags); }
  454. void OverwriteFlags(DWORD dwFlags)
  455. { _dwInheritFlags = dwFlags; }
  456. DWORD GetFlags()
  457. { return _dwInheritFlags; }
  458. };