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.

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