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.

667 lines
16 KiB

  1. /*++
  2. Copyright (c) 1996 Microsoft Corporation
  3. Module Name:
  4. iiscmr.hxx
  5. Abstract:
  6. Classes to handle cert wildcard mapping
  7. Author:
  8. Philippe Choquier (phillich) 17-oct-1996
  9. --*/
  10. #if !defined( _IISCMR_HXX )
  11. #define _IISCMR_HXX
  12. VOID InitializeWildcardMapping( HANDLE hModule );
  13. VOID TerminateWildcardMapping();
  14. typedef BOOL
  15. (WINAPI * SSL_GET_ISSUERS_FN)
  16. (
  17. PBYTE,
  18. LPDWORD
  19. ) ;
  20. //
  21. // X.509 cert fields we recognize
  22. //
  23. enum CERT_FIELD_ID
  24. {
  25. CERT_FIELD_ISSUER,
  26. CERT_FIELD_SUBJECT,
  27. CERT_FIELD_SERIAL_NUMBER,
  28. CERT_FIELD_LAST,
  29. CERT_FIELD_ERROR = 0xffff
  30. } ;
  31. #define CERT_FIELD_FLAG_CONTAINS_SUBFIELDS 0x00000001
  32. //
  33. // Mapper between ASN.1 names ( ASCII format ) & well-known abbreviations
  34. //
  35. typedef struct _MAP_ASN {
  36. LPSTR pAsnName;
  37. LPSTR pTextName;
  38. DWORD dwResId;
  39. } MAP_ASN;
  40. #define INDEX_ERROR 0xffffffff
  41. //
  42. // Mapper between field IDs and well-known field names
  43. //
  44. typedef struct _MAP_FIELD {
  45. CERT_FIELD_ID dwId;
  46. DWORD dwResId;
  47. LPSTR pTextName;
  48. } MAP_FIELD;
  49. #define DBLEN_SIZE 2
  50. #define GETDBLEN(a) (WORD)( ((LPBYTE)a)[1] + (((LPBYTE)a)[0]<<8) )
  51. //
  52. // sub-field match types
  53. //
  54. enum MATCH_TYPES
  55. {
  56. MATCH_ALL = 1, // whole content must match
  57. MATCH_FIRST, // beginning of cert subfield must match
  58. MATCH_LAST, // end of cert subfield must match
  59. MATCH_IN // must be matched inside cer subfield
  60. } ;
  61. //
  62. // X.509 DER encoded certificate partially decoded
  63. //
  64. class CDecodedCert {
  65. public:
  66. dllexp CDecodedCert( PCERT_CONTEXT );
  67. dllexp ~CDecodedCert();
  68. dllexp BOOL GetIssuer( LPVOID* ppCert, LPDWORD pcCert );
  69. dllexp PCERT_RDN_ATTR* GetSubField( CERT_FIELD_ID fi, LPSTR pszAsnName, LPDWORD pdwLen );
  70. private:
  71. PCCERT_CONTEXT pCertCtx;
  72. CERT_RDN_ATTR SerialNumber;
  73. PCERT_NAME_INFO aniFields[CERT_FIELD_LAST];
  74. } ;
  75. //
  76. // Access to array of issuers recognized by the server SSL implementation
  77. // provide conversion between issuer ID & DER encoded issuer
  78. //
  79. class CIssuerStore {
  80. public:
  81. dllexp CIssuerStore();
  82. dllexp ~CIssuerStore();
  83. dllexp VOID Reset();
  84. //
  85. // Read list of issuer from SSL server provider
  86. //
  87. dllexp BOOL LoadServerAcceptedIssuers();
  88. //
  89. // Unserialize from buffer
  90. //
  91. dllexp BOOL Unserialize( LPBYTE* ppb, LPDWORD pc );
  92. dllexp BOOL Unserialize( CStoreXBF* pX );
  93. //
  94. // Serialize to buffer
  95. //
  96. dllexp BOOL Serialize( CStoreXBF* pX );
  97. dllexp VOID Lock()
  98. { EnterCriticalSection( &m_csLock ); }
  99. dllexp VOID Unlock()
  100. { LeaveCriticalSection( &m_csLock ); }
  101. //
  102. // Get count of issuers
  103. //
  104. dllexp DWORD GetNbIssuers()
  105. { return m_IssuerCerts.GetNbEntry(); }
  106. //
  107. // Get issuer DER encoded format by index ( 0-based )
  108. //
  109. dllexp BOOL GetIssuer( DWORD i, LPSTR* ppszIssuerName, LPBYTE* ppIssuer, LPDWORD pcIssuer );
  110. //
  111. // Get issuer DER encoded format by ID
  112. //
  113. dllexp BOOL GetIssuerByName( LPSTR pszIssuerName, LPBYTE* ppIssuer, LPDWORD pcIssuer );
  114. private:
  115. CStrPtrXBF m_pIssuerNames;
  116. CBlobXBF m_IssuerCerts;
  117. CRITICAL_SECTION m_csLock;
  118. BOOL m_fValid;
  119. } ;
  120. //
  121. // Control information global to all rules :
  122. // - rule ordering while checking for a match
  123. // - rules enabled or nor
  124. //
  125. class CCertGlobalRuleInfo {
  126. public:
  127. // global rule API, used by admin tool
  128. dllexp CCertGlobalRuleInfo();
  129. dllexp ~CCertGlobalRuleInfo();
  130. dllexp BOOL IsValid() { return m_fValid; }
  131. dllexp BOOL Reset();
  132. //
  133. // Retrieve ptr to user-editable array of index ( as DWORD ) of rule
  134. // ordering to consider when checking for rule match
  135. // e.g. order is 3, 2, 0, 1 the 4th rule will be considered 1st, then
  136. // the 3rd, ...
  137. //
  138. dllexp LPDWORD GetRuleOrderArray() { return (LPDWORD) m_Order.GetBuff(); }
  139. //
  140. // Get count of rule index in array. Is the same as # of rules in
  141. // CIisRuleMapper object
  142. //
  143. // Win64 fixed
  144. dllexp DWORD GetRuleOrderCount() { return m_Order.GetUsed() / sizeof(DWORD); }
  145. dllexp BOOL AddRuleOrder();
  146. dllexp BOOL DeleteRuleById( DWORD dwId, BOOL DecrementAbove );
  147. //
  148. // Set rules enabled flag
  149. // if FALSE, no wildcard matching will take place
  150. //
  151. dllexp VOID SetRulesEnabled( BOOL f ) { m_fEnabled = f; }
  152. //
  153. // Get rules enabled flag
  154. //
  155. dllexp BOOL GetRulesEnabled() { return m_fEnabled; }
  156. //
  157. // Serialize to buffer
  158. //
  159. dllexp BOOL SerializeGlobalRuleInfo( CStoreXBF* pX);
  160. //
  161. // Unserialize from buffer
  162. //
  163. dllexp BOOL UnserializeGlobalRuleInfo( LPBYTE* ppB, LPDWORD pC );
  164. private:
  165. // old broken code on Win64
  166. // CPtrXBF m_Order;
  167. // Win64 fixed -- added CPtrDwordXBF class to handle Dwords
  168. CPtrDwordXBF m_Order;
  169. BOOL m_fEnabled;
  170. BOOL m_fValid;
  171. } ;
  172. #define CMR_FLAGS_CASE_INSENSITIVE 0x00000001
  173. //
  174. // Individual rule
  175. //
  176. // Rules have a name, target NT account, enabled/disabled status,
  177. // deny access status
  178. //
  179. // Consists of an array of rule elements, each one being a test
  180. // against a cert field/subfield, such as Issuer.O, Subject.CN
  181. // The field designation is stored as a field ID ( CERT_FIELD_ID )
  182. // The sub-field designation is stored as an ASN.1 name ( ascii format )
  183. // The match checking is stored as a byte array which can either
  184. // - be present at the beginning of the cert subfield
  185. // - be present at the end of the cert subfield
  186. // - be present inside the cert subfield
  187. // - be identical to the cert subfield
  188. //
  189. // An array of issuer (stored as Issuer ID, cf. CIssuerStore for
  190. // conversion to/from DER encoded issuer ) can be associated to a rule.
  191. // Each issuer in this array can be flagged as recognized or not.
  192. // If specified, one of the recognized issuers must match the cert issuer
  193. // for a match to occurs.
  194. //
  195. class CCertMapRule {
  196. public:
  197. // rule API. Field is numeric ID ( Issuer, Subject, ...), subfield is ASN.1 ID
  198. // used by admin tool
  199. dllexp CCertMapRule();
  200. dllexp ~CCertMapRule();
  201. dllexp BOOL IsValid() { return m_fValid; }
  202. //
  203. dllexp VOID Reset();
  204. dllexp BOOL Unserialize( LPBYTE* ppb, LPDWORD pc );
  205. dllexp BOOL Unserialize( CStoreXBF* pX );
  206. dllexp BOOL Serialize( CStoreXBF* pX );
  207. // return ERROR_INVALID_NAME if no match
  208. dllexp BOOL Match( CDecodedCert* pC, CDecodedCert* pAuth, LPSTR pszAcct, LPSTR pszPwd,
  209. LPBOOL pfDenied );
  210. //
  211. // Set the rule name ( used by UI only )
  212. //
  213. dllexp BOOL SetRuleName( LPSTR pszName ) { return m_asRuleName.Set( pszName ); }
  214. //
  215. // Get the rule name
  216. //
  217. dllexp LPSTR GetRuleName() { return m_asRuleName.Get(); }
  218. //
  219. // Set the associated NT account
  220. //
  221. // can return FALSE, error ERROR_INVALID_NAME if account syntax invalid
  222. //
  223. dllexp BOOL SetRuleAccount( LPSTR pszAcct );
  224. //
  225. // Get the associated NT account
  226. //
  227. dllexp LPSTR GetRuleAccount() { return m_asAccount.Get(); }
  228. //
  229. // Set the associated NT pwd
  230. //
  231. dllexp BOOL SetRulePassword( LPSTR pszPwd ) { return m_asPassword.Set( pszPwd ); }
  232. //
  233. // Get the associated NT pwd
  234. //
  235. dllexp LPSTR GetRulePassword() { return m_asPassword.Get(); }
  236. //
  237. // Set the rule enabled flag. If disabled, this rule will not be
  238. // consider while searching for a match
  239. //
  240. dllexp VOID SetRuleEnabled( BOOL f ) { m_fEnabled = f; }
  241. //
  242. // Get the rule enabled flag
  243. //
  244. dllexp BOOL GetRuleEnabled() { return m_fEnabled; }
  245. //
  246. // Set the rule deny access flag. If TRUE and a match occurs
  247. // with this rule then access will be denied to the browser
  248. // request
  249. //
  250. dllexp VOID SetRuleDenyAccess( BOOL f ) { m_fDenyAccess = f; }
  251. //
  252. // Get the rule deny access flag
  253. //
  254. dllexp BOOL GetRuleDenyAccess() { return m_fDenyAccess; }
  255. //
  256. // Get the count of rule elements
  257. //
  258. dllexp DWORD GetRuleElemCount() { return m_ElemsContent.GetNbEntry(); }
  259. //
  260. // Retrieve rule element info using index ( 0-based )
  261. // CERT_FIELD_ID, subfield ASN.1 name, content as binary buffer.
  262. // content can be converted to user displayable format using the
  263. // BinaryToMatchRequest() function.
  264. //
  265. dllexp BOOL GetRuleElem( DWORD i, CERT_FIELD_ID* pfiField, LPSTR* ppContent,
  266. LPDWORD pcContent, LPSTR* ppSubField, LPDWORD pdwFlags = NULL );
  267. //
  268. // Delete a rule element by its index
  269. //
  270. dllexp BOOL DeleteRuleElem( DWORD i );
  271. //
  272. // Delete all rule elements whose CERT_FIELD_ID match the one specified
  273. //
  274. dllexp BOOL DeleteRuleElemsByField( CERT_FIELD_ID fiField );
  275. //
  276. // Add a rule element info using index ( 0-based ) where to insert.
  277. // if index is 0xffffffff, rule element is added at the end of
  278. // rule element array
  279. // Must specifiy CERT_FIELD_ID, subfield ASN.1 name,
  280. // content as binary buffer.
  281. // content can be converted from user displayable format using the
  282. // MatchRequestToBinary() function.
  283. //
  284. dllexp DWORD AddRuleElem( DWORD iBefore, CERT_FIELD_ID fiField,
  285. LPSTR pszSubField, LPBYTE pContent, DWORD cContent,
  286. DWORD dwFlags = 0 );
  287. //
  288. // Issuer list : we store issuer ID ( linked to schannel reg entries ) + status
  289. // Issuer ID is HEX2ASCII(MD5(issert cert))
  290. //
  291. // Set the match all issuers flag. If set, the issuer array will be
  292. // disregarded and all issuers will match.
  293. //
  294. dllexp VOID SetMatchAllIssuer( BOOL f ) { m_fMatchAllIssuers = f; }
  295. //
  296. // Get the match all issuers flag
  297. //
  298. dllexp BOOL GetMatchAllIssuer() { return m_fMatchAllIssuers; }
  299. //
  300. // Get count of issuer in array
  301. //
  302. dllexp DWORD GetIssuerCount() { return m_Issuers.GetNbEntry(); }
  303. //
  304. // Retrieve issuer info by index ( 0-based )
  305. // ID ( cf. CIssuerStore for conversion
  306. // to/from ID <> DER encoded issuer ), accept flag
  307. // The ID is returned as a ptr to internal storage, not to be
  308. // alloced or freed.
  309. //
  310. dllexp BOOL GetIssuerEntry( DWORD i, LPBOOL pfS, LPSTR* ppszI);
  311. //
  312. // Retrieve issuer accept status by ID
  313. //
  314. dllexp BOOL GetIssuerEntryByName( LPSTR pszName, LPBOOL pfS );
  315. //
  316. // Set issue accept flag using index ( 0-based )
  317. //
  318. dllexp BOOL SetIssuerEntryAcceptStatus( DWORD, BOOL );
  319. //
  320. // Add issuer entry : ID, accept status
  321. // ID must come from CIssuerStore
  322. //
  323. dllexp BOOL AddIssuerEntry( LPSTR pszName, BOOL fAcceptStatus );
  324. //
  325. // Delete issuer entry by index ( 0-based )
  326. //
  327. dllexp BOOL DeleteIssuerEntry( DWORD i );
  328. private:
  329. CAllocString m_asRuleName;
  330. CAllocString m_asAccount;
  331. CAllocString m_asPassword;
  332. BOOL m_fEnabled;
  333. BOOL m_fDenyAccess;
  334. CBlobXBF m_ElemsContent; // content to match
  335. // prefix ( MATCH_TYPES ) :
  336. // MATCH_ALL : must be exact match
  337. // MATCH_FIRST : must match 1st n char
  338. // MATCH_LAST : must match last n char
  339. // MATCH_IN : must match n char in content
  340. // followed by length of match, then match
  341. CStrPtrXBF m_ElemsSubfield; // ASN.1 ID
  342. CPtrXBF m_ElemsField; // field ID ( CERT_FIELD_ID )
  343. CPtrXBF m_ElemsFlags;
  344. //
  345. // NOTE : In IIS 5, we no longer use any of these fields but we're keeping them
  346. // so that we can still read out and use IIS 4 mappings
  347. //
  348. CStrPtrXBF m_Issuers;
  349. CPtrXBF m_IssuersAcceptStatus;
  350. BOOL m_fMatchAllIssuers;
  351. BOOL m_fValid;
  352. } ;
  353. class CIisRuleMapper {
  354. public:
  355. dllexp CIisRuleMapper();
  356. dllexp ~CIisRuleMapper();
  357. dllexp BOOL IsValid() { return m_fValid; }
  358. dllexp BOOL Reset();
  359. //
  360. // Lock rules. Must be called before modifying any information
  361. // or calling Match()
  362. //
  363. dllexp VOID LockRules()
  364. { EnterCriticalSection( &m_csLock ); }
  365. //
  366. // Unlock rules
  367. //
  368. dllexp VOID UnlockRules()
  369. { LeaveCriticalSection( &m_csLock ); }
  370. dllexp BOOL Load( LPSTR pszInstanceId );
  371. dllexp BOOL Save( LPSTR pszInstanceId );
  372. //
  373. // Serialize all rules info to buffer
  374. //
  375. dllexp BOOL Serialize( CStoreXBF* pX );
  376. //
  377. // Un-serialize all rules from buffer ( using extensible buffer class )
  378. //
  379. dllexp BOOL Unserialize( CStoreXBF* pX );
  380. //
  381. // Un-serialize all rules from buffer
  382. //
  383. dllexp BOOL Unserialize( LPBYTE*, LPDWORD );
  384. //
  385. // Get count of rules
  386. //
  387. dllexp DWORD GetRuleCount()
  388. { return m_fValid ? m_Rules.GetNbPtr() : 0; }
  389. //
  390. // Delete a rule by index ( 0-based )
  391. //
  392. dllexp BOOL DeleteRule( DWORD dwI );
  393. //
  394. // Add an empty new rule at end of rule array.
  395. // Use GetGlobalRulesInfo()->GetRuleOrderArray() to access/update
  396. // array specifying rule ordering.
  397. // Use GetRule() then CCertMapRule API to access/update the created rule.
  398. //
  399. dllexp DWORD AddRule(); // @ end, use SetRuleOrder ( default is last pos )
  400. dllexp DWORD AddRule(CCertMapRule*); // @ end, use SetRuleOrder ( default is last pos )
  401. //
  402. // look for a matching rule and resulting NT account
  403. // given DER encoded cert.
  404. // If returns error ( FALSE ), GetLastError() can be the following :
  405. // - ERROR_ACCESS_DENIED if access denied
  406. // - ERROR_INVALID_NAME if not found
  407. // - ERROR_ARENA_TRASHED if invalid internal state
  408. // returns addr of NT account in pszAcct, buffer assumed to be big enough
  409. // before to insure ptr remains valid until Unlock()
  410. //
  411. dllexp BOOL Match( PCERT_CONTEXT pCert, PCERT_CONTEXT pAuth, LPSTR pszAcct, LPSTR pszPwd );
  412. //
  413. // Retrieve ptr to rule by index ( 0-based )
  414. // You can then use the CCertMapRule API to access/update rule properties
  415. //
  416. dllexp CCertMapRule* GetRule( DWORD dwI ) // for ser/unser/set/get purpose
  417. { return m_fValid && dwI < m_Rules.GetNbPtr() ? (CCertMapRule*)m_Rules.GetPtr(dwI) : NULL; }
  418. //
  419. // Access global rule info ( common to all rules )
  420. // cf. CCertGlobalRuleInfo
  421. //
  422. dllexp CCertGlobalRuleInfo* GetGlobalRulesInfo() // for ser/unser/set/get purpose
  423. { return &m_GlobalRuleInfo; }
  424. private:
  425. CRITICAL_SECTION m_csLock;
  426. CCertGlobalRuleInfo m_GlobalRuleInfo;
  427. CPtrXBF m_Rules;
  428. BOOL m_fValid;
  429. } ;
  430. //
  431. // Helper functions
  432. //
  433. //
  434. // convert match request to/from internal format
  435. //
  436. //
  437. // Map user displayable sub-field content to internal format
  438. // result must be freed using FreeMatchConversion
  439. //
  440. dllexp BOOL MatchRequestToBinary( LPSTR pszReq, LPBYTE* ppbBin, LPDWORD pdwBin );
  441. //
  442. // Map internal format to user displayable content
  443. // result must be freed using FreeMatchConversion
  444. //
  445. dllexp BOOL BinaryToMatchRequest( LPBYTE pbBin, DWORD dwBin, LPSTR* ppszReq );
  446. //
  447. // Free result of the 2 previous map API
  448. //
  449. dllexp VOID FreeMatchConversion( LPVOID );
  450. //
  451. // Map field displayable name ( from a MAP_FIELD array )
  452. // to CERT_FIELD_ID. returns CERT_FIELD_ERROR if no match
  453. //
  454. dllexp CERT_FIELD_ID MapFieldToId( LPSTR pField );
  455. //
  456. // Map CERT_FIELD_ID to field displayable name ( from a MAP_FIELD array )
  457. //
  458. dllexp LPSTR MapIdToField( CERT_FIELD_ID dwId );
  459. //
  460. // Get flags for specified CERT_FIELD_ID
  461. //
  462. dllexp DWORD GetIdFlags( CERT_FIELD_ID dwId );
  463. //
  464. // Map sub field displayable name ( e.g. O, OU, CN, ... )
  465. // to ASN.1 name ( as an ascii string )
  466. // returns NULL if no match
  467. //
  468. dllexp LPSTR MapSubFieldToAsn1( LPSTR pszSubField );
  469. //
  470. // Map ASN.1 name ( as an ascii string )
  471. // to sub field displayable name ( e.g. O, OU, CN, ... )
  472. // returns ASN.1 name if no match
  473. //
  474. dllexp LPSTR MapAsn1ToSubField( LPSTR pszAsn1 );
  475. //
  476. // Enumerate known subfields
  477. //
  478. dllexp LPSTR EnumerateKnownSubFields( DWORD dwIndex );
  479. LPBYTE
  480. memstr(
  481. LPBYTE pStr,
  482. UINT cStr,
  483. LPBYTE pSub,
  484. UINT cSub,
  485. BOOL fCaseInsensitive
  486. );
  487. dllexp VOID
  488. FreeCIisRuleMapper(
  489. LPVOID pMapper
  490. );
  491. dllexp
  492. BOOL
  493. GetDefaultIssuers(
  494. LPBYTE pIssuer,
  495. DWORD * pdwIssuer
  496. );
  497. #endif
  498.