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.

695 lines
15 KiB

  1. // ipaccess.cpp : Implementation of CTcpAccess & CTcpAccessExceptions.
  2. #include "stdafx.h"
  3. #include "pudebug.h"
  4. #define _RDNS_STANDALONE
  5. #include <rdns.hxx>
  6. DECLARE_DEBUG_PRINTS_OBJECT()
  7. #include "nntpcmn.h"
  8. #include "cmultisz.h"
  9. #include "ipaccess.h"
  10. #include "oleutil.h"
  11. #include "metautil.h"
  12. #include "metakey.h"
  13. // Must define THIS_FILE_* macros to use NntpCreateException()
  14. #define THIS_FILE_HELP_CONTEXT 0
  15. #define THIS_FILE_PROG_ID _T("Nntpadm.TcpAccess.1")
  16. #define THIS_FILE_IID IID_ITcpAccess
  17. //
  18. // Useful macros:
  19. //
  20. #define MAKEIPADDRESS(b1,b2,b3,b4) (((DWORD)(b1)<<24) +\
  21. ((DWORD)(b2)<<16) +\
  22. ((DWORD)(b3)<< 8) +\
  23. ((DWORD)(b4)))
  24. #define GETIP_FIRST(x) ((x>>24) & 0xff)
  25. #define GETIP_SECOND(x) ((x>>16) & 0xff)
  26. #define GETIP_THIRD(x) ((x>> 8) & 0xff)
  27. #define GETIP_FOURTH(x) ((x) & 0xff)
  28. inline void
  29. DWORDtoLPBYTE (
  30. IN DWORD dw,
  31. OUT LPBYTE lpBytes
  32. )
  33. {
  34. _ASSERT ( !IsBadWritePtr ( lpBytes, 4 * sizeof ( BYTE ) ) );
  35. lpBytes[0] = (BYTE)GETIP_FIRST(dw);
  36. lpBytes[1] = (BYTE)GETIP_SECOND(dw);
  37. lpBytes[2] = (BYTE)GETIP_THIRD(dw);
  38. lpBytes[3] = (BYTE)GETIP_FOURTH(dw);
  39. }
  40. /////////////////////////////////////////////////////////////////////////////
  41. //
  42. STDMETHODIMP CTcpAccess::InterfaceSupportsErrorInfo(REFIID riid)
  43. {
  44. static const IID* arr[] =
  45. {
  46. &IID_ITcpAccess,
  47. };
  48. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  49. {
  50. if (InlineIsEqualGUID(*arr[i],riid))
  51. return S_OK;
  52. }
  53. return S_FALSE;
  54. }
  55. CTcpAccess::CTcpAccess ()
  56. // CComBSTR's are initialized to NULL by default.
  57. {
  58. m_pGrantList = NULL;
  59. m_pDenyList = NULL;
  60. }
  61. CTcpAccess::~CTcpAccess ()
  62. {
  63. // All CComBSTR's are freed automatically.
  64. if ( m_pGrantList ) {
  65. m_pGrantList->Release ();
  66. }
  67. if ( m_pDenyList ) {
  68. m_pDenyList->Release ();
  69. }
  70. }
  71. HRESULT CTcpAccess::GetAddressCheckFromMetabase ( CMetabaseKey * pMB, ADDRESS_CHECK * pAC )
  72. {
  73. HRESULT hr = NOERROR;
  74. DWORD dwDummy = 0;
  75. DWORD cbIpSec = 0;
  76. BYTE * pIpSec = NULL;
  77. hr = pMB->GetDataSize ( _T(""), MD_IP_SEC, BINARY_METADATA, &cbIpSec, METADATA_INHERIT, IIS_MD_UT_FILE );
  78. if ( hr == MD_ERROR_DATA_NOT_FOUND ) {
  79. hr = NOERROR;
  80. cbIpSec = 0;
  81. }
  82. BAIL_ON_FAILURE ( hr );
  83. if ( cbIpSec != 0 ) {
  84. pIpSec = new BYTE [ cbIpSec ];
  85. if ( !pIpSec ) {
  86. BAIL_WITH_FAILURE ( hr, E_OUTOFMEMORY );
  87. }
  88. hr = pMB->GetBinary ( MD_IP_SEC, pIpSec, cbIpSec, METADATA_INHERIT, IIS_MD_UT_FILE );
  89. BAIL_ON_FAILURE (hr);
  90. pAC->BindCheckList ( pIpSec, cbIpSec );
  91. }
  92. Exit:
  93. return hr;
  94. }
  95. //////////////////////////////////////////////////////////////////////
  96. // Private admin object interface:
  97. //////////////////////////////////////////////////////////////////////
  98. HRESULT CTcpAccess::GetFromMetabase ( CMetabaseKey * pMB )
  99. {
  100. HRESULT hr = NULL;
  101. CComObject<CTcpAccessExceptions> * pGrantList = NULL;
  102. CComObject<CTcpAccessExceptions> * pDenyList = NULL;
  103. ADDRESS_CHECK ac;
  104. hr = GetAddressCheckFromMetabase ( pMB, &ac );
  105. BAIL_ON_FAILURE ( hr );
  106. hr = CComObject<CTcpAccessExceptions>::CreateInstance ( &pGrantList );
  107. BAIL_ON_FAILURE(hr);
  108. hr = CComObject<CTcpAccessExceptions>::CreateInstance ( &pDenyList );
  109. BAIL_ON_FAILURE(hr);
  110. //
  111. // Copy each list into our object:
  112. //
  113. hr = pGrantList->FromAddressCheck ( &ac, TRUE );
  114. BAIL_ON_FAILURE(hr);
  115. hr = pDenyList->FromAddressCheck ( &ac, FALSE );
  116. BAIL_ON_FAILURE(hr);
  117. //
  118. // Replace the old grant & deny lists with the new ones:
  119. //
  120. if ( m_pGrantList ) {
  121. m_pGrantList->Release ();
  122. m_pGrantList = NULL;
  123. }
  124. if ( m_pDenyList ) {
  125. m_pDenyList->Release ();
  126. m_pDenyList = NULL;
  127. }
  128. m_pGrantList = pGrantList;
  129. m_pDenyList = pDenyList;
  130. m_pGrantList->AddRef ();
  131. m_pDenyList->AddRef ();
  132. Exit:
  133. ac.UnbindCheckList ();
  134. if ( FAILED(hr) ) {
  135. delete pGrantList;
  136. delete pDenyList;
  137. }
  138. return hr;
  139. }
  140. HRESULT CTcpAccess::SendToMetabase ( CMetabaseKey * pMB )
  141. {
  142. HRESULT hr;
  143. ADDRESS_CHECK ac;
  144. BYTE * pIpSec = NULL;
  145. DWORD cbIpSec = 0;
  146. _ASSERT ( m_pGrantList );
  147. _ASSERT ( m_pDenyList );
  148. ac.BindCheckList ();
  149. hr = m_pGrantList->ToAddressCheck ( &ac, TRUE );
  150. BAIL_ON_FAILURE(hr);
  151. hr = m_pDenyList->ToAddressCheck ( &ac, FALSE );
  152. BAIL_ON_FAILURE(hr);
  153. cbIpSec = ac.QueryCheckListSize ();
  154. pIpSec = ac.QueryCheckListPtr ();
  155. hr = pMB->SetBinary ( MD_IP_SEC, pIpSec, cbIpSec, METADATA_INHERIT | METADATA_REFERENCE, IIS_MD_UT_FILE );
  156. Exit:
  157. return hr;
  158. }
  159. //////////////////////////////////////////////////////////////////////
  160. // Properties:
  161. //////////////////////////////////////////////////////////////////////
  162. STDMETHODIMP CTcpAccess::get_GrantedList ( ITcpAccessExceptions ** ppGrantedList )
  163. {
  164. return m_pGrantList->QueryInterface ( IID_ITcpAccessExceptions, (void **) ppGrantedList );
  165. }
  166. STDMETHODIMP CTcpAccess::get_DeniedList ( ITcpAccessExceptions ** ppDeniedList )
  167. {
  168. return m_pDenyList->QueryInterface ( IID_ITcpAccessExceptions, (void **) ppDeniedList );
  169. }
  170. /////////////////////////////////////////////////////////////////////////////
  171. //
  172. STDMETHODIMP CTcpAccessExceptions::InterfaceSupportsErrorInfo(REFIID riid)
  173. {
  174. static const IID* arr[] =
  175. {
  176. &IID_ITcpAccessExceptions,
  177. };
  178. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  179. {
  180. if (InlineIsEqualGUID(*arr[i],riid))
  181. return S_OK;
  182. }
  183. return S_FALSE;
  184. }
  185. CTcpAccessExceptions::CTcpAccessExceptions () :
  186. m_cCount ( 0 ),
  187. m_rgItems ( NULL )
  188. // CComBSTR's are initialized to NULL by default.
  189. {
  190. }
  191. CTcpAccessExceptions::~CTcpAccessExceptions ()
  192. {
  193. // All CComBSTR's are freed automatically.
  194. }
  195. HRESULT
  196. CTcpAccessExceptions::FromAddressCheck (
  197. ADDRESS_CHECK * pAC,
  198. BOOL fGrantList
  199. )
  200. {
  201. HRESULT hr = NOERROR;
  202. DWORD cNames;
  203. DWORD cAddresses;
  204. DWORD i;
  205. cNames = pAC->GetNbName ( fGrantList );
  206. cAddresses = pAC->GetNbAddr ( fGrantList );
  207. //
  208. // Copy the Dns Names:
  209. //
  210. for ( i = 0; i < cNames; i++ ) {
  211. DWORD dwFlags = 0;
  212. LPSTR lpName = NULL;
  213. CComBSTR strDomain;
  214. if ( pAC->GetName ( fGrantList, i, &lpName, &dwFlags ) ) {
  215. if ( !(dwFlags & DNSLIST_FLAG_NOSUBDOMAIN) ) {
  216. strDomain = _T("*.");
  217. strDomain.Append ( lpName );
  218. }
  219. else {
  220. strDomain = lpName;
  221. }
  222. hr = AddDnsName ( strDomain );
  223. BAIL_ON_FAILURE(hr);
  224. }
  225. }
  226. //
  227. // Copy the IpAddresses:
  228. //
  229. for ( i = 0; i < cAddresses; i++ ) {
  230. DWORD dwFlags = 0;
  231. LPBYTE lpMask = NULL;
  232. LPBYTE lpAddr = NULL;
  233. DWORD dwIpAddress;
  234. DWORD dwIpMask;
  235. if ( pAC->GetAddr ( fGrantList, i, &dwFlags, &lpMask, &lpAddr ) ) {
  236. dwIpAddress = MAKEIPADDRESS( lpAddr[0], lpAddr[1], lpAddr[2], lpAddr[3] );
  237. dwIpMask = MAKEIPADDRESS( lpMask[0], lpMask[1], lpMask[2], lpMask[3] );
  238. hr = AddIpAddress ( (long) dwIpAddress, (long) dwIpMask );
  239. BAIL_ON_FAILURE(hr);
  240. }
  241. }
  242. Exit:
  243. return hr;
  244. }
  245. HRESULT
  246. CTcpAccessExceptions::ToAddressCheck (
  247. ADDRESS_CHECK * pAC,
  248. BOOL fGrantList
  249. )
  250. {
  251. HRESULT hr = NOERROR;
  252. long i;
  253. for ( i = 0; i < m_cCount; i++ ) {
  254. BOOL fIsName = FALSE;
  255. BOOL fIsAddr = FALSE;
  256. m_rgItems[i]->get_IsDnsName ( &fIsName );
  257. m_rgItems[i]->get_IsIpAddress ( &fIsAddr );
  258. if ( fIsName ) {
  259. CComBSTR strDnsName;
  260. DWORD cchName = 0;
  261. LPSTR szAnsiName = NULL;
  262. DWORD dwFlags = 0;
  263. LPSTR lpName = NULL;
  264. hr = m_rgItems[i]->get_DnsName ( &strDnsName );
  265. BAIL_ON_FAILURE(hr);
  266. cchName = strDnsName.Length ( );
  267. szAnsiName = new char [ cchName + 1 ];
  268. if ( !szAnsiName ) {
  269. BAIL_WITH_FAILURE( hr, E_OUTOFMEMORY );
  270. }
  271. WideCharToMultiByte ( CP_ACP, 0, strDnsName, -1, szAnsiName, cchName + 1, NULL, NULL );
  272. if ( strncmp ( szAnsiName, "*.", 2 ) == 0 ) {
  273. dwFlags = 0;
  274. lpName = szAnsiName + 2;
  275. }
  276. else {
  277. dwFlags |= DNSLIST_FLAG_NOSUBDOMAIN;
  278. lpName = szAnsiName;
  279. }
  280. pAC->AddName ( fGrantList, lpName, dwFlags );
  281. delete szAnsiName;
  282. }
  283. else if ( fIsAddr ) {
  284. long lIpAddress = 0;
  285. long lIpMask = 0;
  286. BYTE bIp[4];
  287. BYTE bMask[4];
  288. m_rgItems[i]->get_IpAddress ( &lIpAddress );
  289. m_rgItems[i]->get_IpMask ( &lIpMask );
  290. DWORDtoLPBYTE ( (DWORD) lIpAddress, bIp );
  291. DWORDtoLPBYTE ( (DWORD) lIpMask, bMask );
  292. pAC->AddAddr ( fGrantList, AF_INET, bMask, bIp );
  293. }
  294. }
  295. Exit:
  296. return hr;
  297. }
  298. //////////////////////////////////////////////////////////////////////
  299. // Properties:
  300. //////////////////////////////////////////////////////////////////////
  301. STDMETHODIMP CTcpAccessExceptions::get_Count ( long * pcCount )
  302. {
  303. return StdPropertyGet ( m_cCount, pcCount );
  304. }
  305. STDMETHODIMP CTcpAccessExceptions::AddDnsName ( BSTR strDnsName )
  306. {
  307. HRESULT hr = NOERROR;
  308. CComPtr<ITcpAccessException> pNew;
  309. hr = CTcpAccessException::CreateNew ( strDnsName, &pNew );
  310. BAIL_ON_FAILURE ( hr );
  311. hr = AddItem ( pNew );
  312. BAIL_ON_FAILURE ( hr );
  313. Exit:
  314. return hr;
  315. }
  316. STDMETHODIMP CTcpAccessExceptions::AddIpAddress ( long lIpAddress, long lIpMask )
  317. {
  318. HRESULT hr = NOERROR;
  319. CComPtr<ITcpAccessException> pNew;
  320. hr = CTcpAccessException::CreateNew ( lIpAddress, lIpMask, &pNew );
  321. BAIL_ON_FAILURE ( hr );
  322. hr = AddItem ( pNew );
  323. BAIL_ON_FAILURE ( hr );
  324. Exit:
  325. return hr;
  326. }
  327. HRESULT CTcpAccessExceptions::AddItem ( ITcpAccessException * pNew )
  328. {
  329. HRESULT hr = NOERROR;
  330. CComPtr<ITcpAccessException> * rgNewItems = NULL;
  331. long i;
  332. rgNewItems = new CComPtr<ITcpAccessException> [ m_cCount + 1 ];
  333. if ( !rgNewItems ) {
  334. BAIL_WITH_FAILURE ( hr, E_OUTOFMEMORY );
  335. }
  336. for ( i = 0; i < m_cCount; i++ ) {
  337. rgNewItems[i] = m_rgItems[i];
  338. }
  339. rgNewItems[m_cCount] = pNew;
  340. delete [] m_rgItems;
  341. m_rgItems = rgNewItems;
  342. m_cCount++;
  343. Exit:
  344. return hr;
  345. }
  346. STDMETHODIMP CTcpAccessExceptions::Item ( long index, ITcpAccessException ** ppTcpAccessException )
  347. {
  348. HRESULT hr;
  349. if ( index < 0 || index >= m_cCount ) {
  350. return NntpCreateException ( IDS_NNTPEXCEPTION_INVALID_INDEX );
  351. }
  352. hr = m_rgItems[index]->QueryInterface ( IID_ITcpAccessException, (void **) ppTcpAccessException );
  353. return hr;
  354. }
  355. STDMETHODIMP CTcpAccessExceptions::Remove ( long index )
  356. {
  357. HRESULT hr = NOERROR;
  358. CComPtr<ITcpAccessException> pTemp;
  359. long i;
  360. if ( index < 0 || index >= m_cCount ) {
  361. return NntpCreateException ( IDS_NNTPEXCEPTION_INVALID_INDEX );
  362. }
  363. for ( i = index + 1; i < m_cCount; i++ ) {
  364. m_rgItems[i - 1] = m_rgItems[i];
  365. }
  366. m_rgItems[m_cCount - 1].Release ();
  367. m_cCount--;
  368. return hr;
  369. }
  370. STDMETHODIMP
  371. CTcpAccessExceptions::FindDnsIndex (
  372. BSTR strDnsNameToFind,
  373. long * pIndex
  374. )
  375. {
  376. long lResult = -1;
  377. long i;
  378. for ( i = 0; i < m_cCount; i++ ) {
  379. HRESULT hr1;
  380. CComBSTR strDnsName;
  381. BOOL fIsDnsName = FALSE;
  382. hr1 = m_rgItems[i]->get_IsDnsName ( &fIsDnsName );
  383. if ( !fIsDnsName ) {
  384. continue;
  385. }
  386. hr1 = m_rgItems[i]->get_DnsName ( &strDnsName );
  387. if ( SUCCEEDED(hr1) &&
  388. !lstrcmpi ( strDnsName, strDnsNameToFind ) ) {
  389. lResult = i;
  390. break;
  391. }
  392. }
  393. *pIndex = lResult;
  394. return NOERROR;
  395. }
  396. STDMETHODIMP
  397. CTcpAccessExceptions::FindIpIndex (
  398. long lIpAddressToFind,
  399. long lIpMaskToFind,
  400. long * pIndex
  401. )
  402. {
  403. long lResult = -1;
  404. long i;
  405. for ( i = 0; i < m_cCount; i++ ) {
  406. BOOL fIsIpAddress = FALSE;
  407. long lIpAddress;
  408. long lIpMask;
  409. m_rgItems[i]->get_IsIpAddress ( &fIsIpAddress );
  410. if ( !fIsIpAddress ) {
  411. continue;
  412. }
  413. m_rgItems[i]->get_IpAddress ( &lIpAddress );
  414. m_rgItems[i]->get_IpMask ( &lIpMask );
  415. if ( lIpAddress == lIpAddressToFind && lIpMask == lIpMaskToFind ) {
  416. lResult = i;
  417. break;
  418. }
  419. }
  420. *pIndex = lResult;
  421. return NOERROR;
  422. }
  423. STDMETHODIMP CTcpAccessExceptions::Clear ( )
  424. {
  425. delete [] m_rgItems;
  426. m_rgItems = NULL;
  427. m_cCount = 0;
  428. return NOERROR;
  429. }
  430. /////////////////////////////////////////////////////////////////////////////
  431. //
  432. STDMETHODIMP CTcpAccessException::InterfaceSupportsErrorInfo(REFIID riid)
  433. {
  434. static const IID* arr[] =
  435. {
  436. &IID_ITcpAccessException,
  437. };
  438. for (int i=0;i<sizeof(arr)/sizeof(arr[0]);i++)
  439. {
  440. if (InlineIsEqualGUID(*arr[i],riid))
  441. return S_OK;
  442. }
  443. return S_FALSE;
  444. }
  445. CTcpAccessException::CTcpAccessException () :
  446. m_fIsDnsName ( FALSE ),
  447. m_fIsIpAddress ( FALSE ),
  448. m_dwIpAddress ( 0 ),
  449. m_dwIpMask ( 0 )
  450. // CComBSTR's are initialized to NULL by default.
  451. {
  452. }
  453. CTcpAccessException::~CTcpAccessException ()
  454. {
  455. // All CComBSTR's are freed automatically.
  456. }
  457. HRESULT
  458. CTcpAccessException::CreateNew (
  459. LPWSTR strDnsName,
  460. ITcpAccessException ** ppNew
  461. )
  462. {
  463. HRESULT hr;
  464. CComObject<CTcpAccessException> * pNew = NULL;
  465. hr = CComObject<CTcpAccessException>::CreateInstance ( &pNew );
  466. BAIL_ON_FAILURE(hr);
  467. hr = pNew->put_DnsName ( strDnsName );
  468. BAIL_ON_FAILURE(hr);
  469. hr = pNew->QueryInterface ( IID_ITcpAccessException, (void **) ppNew );
  470. BAIL_ON_FAILURE(hr);
  471. Exit:
  472. if ( FAILED(hr) ) {
  473. delete pNew;
  474. }
  475. return hr;
  476. }
  477. HRESULT
  478. CTcpAccessException::CreateNew (
  479. DWORD dwIpAddress,
  480. DWORD dwIpMask,
  481. ITcpAccessException ** ppNew
  482. )
  483. {
  484. HRESULT hr;
  485. CComObject<CTcpAccessException> * pNew = NULL;
  486. hr = CComObject<CTcpAccessException>::CreateInstance ( &pNew );
  487. BAIL_ON_FAILURE(hr);
  488. hr = pNew->put_IpAddress ( (long) dwIpAddress );
  489. hr = pNew->put_IpMask ( (long) dwIpMask );
  490. hr = pNew->QueryInterface ( IID_ITcpAccessException, (void **) ppNew );
  491. BAIL_ON_FAILURE(hr);
  492. Exit:
  493. if ( FAILED(hr) ) {
  494. delete pNew;
  495. }
  496. return hr;
  497. }
  498. //////////////////////////////////////////////////////////////////////
  499. // Properties:
  500. //////////////////////////////////////////////////////////////////////
  501. STDMETHODIMP CTcpAccessException::get_IsDnsName ( BOOL * pfIsDnsName )
  502. {
  503. return StdPropertyGet ( m_fIsDnsName, pfIsDnsName );
  504. }
  505. STDMETHODIMP CTcpAccessException::get_IsIpAddress ( BOOL * pfIsIpAddress )
  506. {
  507. return StdPropertyGet ( m_fIsIpAddress, pfIsIpAddress );
  508. }
  509. STDMETHODIMP CTcpAccessException::get_DnsName ( BSTR * pstrDnsName )
  510. {
  511. return StdPropertyGet ( m_strDnsName, pstrDnsName );
  512. }
  513. STDMETHODIMP CTcpAccessException::put_DnsName ( BSTR strDnsName )
  514. {
  515. HRESULT hr;
  516. hr = StdPropertyPut ( &m_strDnsName, strDnsName );
  517. if ( SUCCEEDED(hr) ) {
  518. m_fIsDnsName = TRUE;
  519. m_fIsIpAddress = FALSE;
  520. }
  521. return hr;
  522. }
  523. STDMETHODIMP CTcpAccessException::get_IpAddress ( long * plIpAddress )
  524. {
  525. return StdPropertyGet ( m_dwIpAddress, plIpAddress );
  526. }
  527. STDMETHODIMP CTcpAccessException::put_IpAddress ( long lIpAddress )
  528. {
  529. HRESULT hr;
  530. hr = StdPropertyPut ( &m_dwIpAddress, lIpAddress );
  531. if ( SUCCEEDED(hr) ) {
  532. m_fIsDnsName = FALSE;
  533. m_fIsIpAddress = TRUE;
  534. }
  535. return hr;
  536. }
  537. STDMETHODIMP CTcpAccessException::get_IpMask ( long * plIpMask )
  538. {
  539. return StdPropertyGet ( m_dwIpMask, plIpMask );
  540. }
  541. STDMETHODIMP CTcpAccessException::put_IpMask ( long lIpMask )
  542. {
  543. return StdPropertyPut ( &m_dwIpMask, lIpMask );
  544. }