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.

587 lines
13 KiB

  1. // to be linked with:
  2. // uuid.lib ole32.lib user32.lib kernel32.lib advapi32.lib wsock32.lib
  3. // iis\svcs\infocomm\rdns\obj\i386\isrdns.lib iis\svcs\lib\i386\tsstr.lib iis\svcs\lib\i386\isdebug.lib
  4. #include "stdafx.h"
  5. #ifndef _CHICAGO_
  6. #define _RDNS_STANDALONE
  7. #include <winsock2.h>
  8. #include <rdns.hxx>
  9. #include <buffer.hxx>
  10. #include <ole2.h>
  11. #include <iadm.h>
  12. #include <iiscnfg.h>
  13. #include "mdkey.h"
  14. #include "mdentry.h"
  15. #include "helper.h"
  16. #include <inetinfo.h>
  17. extern int g_CheckIfMetabaseValueWasWritten;
  18. #define TIMEOUT_VALUE 5000
  19. //
  20. // Global Data
  21. //
  22. //
  23. // The registry parameter key names for the grant list and deny
  24. // list. We use the kludgemultisz thing for Chicago
  25. //
  26. #define IPSEC_DENY_LIST L"Deny IP List"
  27. #define IPSEC_GRANT_LIST L"Grant IP List"
  28. //
  29. // Private prototypes.
  30. //
  31. BOOL
  32. DottedDecimalToDword(
  33. CHAR * * ppszAddress,
  34. DWORD * pdwAddress
  35. );
  36. CHAR *
  37. KludgeMultiSz(
  38. HKEY hkey,
  39. LPDWORD lpdwLength
  40. )
  41. {
  42. LONG err;
  43. DWORD iValue;
  44. DWORD cchTotal;
  45. DWORD cchValue;
  46. CHAR szValue[MAX_PATH];
  47. LPSTR lpMultiSz;
  48. LPSTR lpTmp;
  49. LPSTR lpEnd;
  50. //
  51. // Enumerate the values and total up the lengths.
  52. //
  53. iValue = 0;
  54. cchTotal = 0;
  55. for( ; ; )
  56. {
  57. cchValue = sizeof(szValue);
  58. err = RegEnumValueA( hkey,
  59. iValue,
  60. szValue,
  61. &cchValue,
  62. NULL,
  63. NULL,
  64. NULL,
  65. NULL );
  66. if( err != NO_ERROR )
  67. {
  68. break;
  69. }
  70. //
  71. // Add the length of the value's name, plus one
  72. // for the terminator.
  73. //
  74. cchTotal += strlen( szValue ) + 1;
  75. //
  76. // Advance to next value.
  77. //
  78. iValue++;
  79. }
  80. //
  81. // Add one for the final terminating NULL.
  82. //
  83. cchTotal++;
  84. *lpdwLength = cchTotal;
  85. //
  86. // Allocate the MULTI_SZ buffer.
  87. //
  88. lpMultiSz = (CHAR *) LocalAlloc( LMEM_FIXED, cchTotal * sizeof(CHAR) );
  89. if( lpMultiSz == NULL )
  90. {
  91. SetLastError( ERROR_NOT_ENOUGH_MEMORY );
  92. return NULL;
  93. }
  94. memset( lpMultiSz, 0, cchTotal * sizeof(CHAR) );
  95. //
  96. // Enumerate the values and append to the buffer.
  97. //
  98. iValue = 0;
  99. lpTmp = lpMultiSz;
  100. lpEnd = lpMultiSz + cchTotal;
  101. for( ; ; )
  102. {
  103. cchValue = sizeof(szValue)/sizeof(CHAR);
  104. err = RegEnumValueA( hkey,
  105. iValue,
  106. szValue,
  107. &cchValue,
  108. NULL,
  109. NULL,
  110. NULL,
  111. NULL );
  112. if( err != NO_ERROR )
  113. {
  114. break;
  115. }
  116. //
  117. // Compute the length of the value name (including
  118. // the terminating NULL).
  119. //
  120. cchValue = strlen( szValue ) + 1;
  121. //
  122. // Determine if there is room in the array, taking into
  123. // account the second NULL that terminates the string list.
  124. //
  125. if( ( lpTmp + cchValue + 1 ) > lpEnd )
  126. {
  127. break;
  128. }
  129. //
  130. // Append the value name.
  131. //
  132. strcpy( lpTmp, szValue );
  133. lpTmp += cchValue;
  134. //
  135. // Advance to next value.
  136. //
  137. iValue++;
  138. }
  139. //
  140. // Success!
  141. //
  142. return (LPSTR)lpMultiSz;
  143. } // KludgeMultiSz
  144. BOOL
  145. ReadIPList(
  146. LPWSTR pszRegKey,
  147. LPWSTR pszRegSubKey,
  148. INETA_IP_SEC_LIST** ppIpSec
  149. )
  150. /*++
  151. Description:
  152. This function reads the IP list from registry location
  153. specified in the pszRegKey + pszRegSubKey and stores the list in the
  154. internal list in memory.
  155. If there are no entries in the registry then this returns
  156. a NULL IP Security list object.
  157. If there is a new list, this function also frees the old list
  158. present in *ppIPSecList
  159. Arguments:
  160. pszRegKey - pointer to string containing the registry key
  161. where pszRegSubKey is located
  162. pszRegSubKey - pointer to string containing the registry key
  163. where IP list is stored relative to pszRegKey
  164. Returns:
  165. TRUE on success and FALSE on failure
  166. --*/
  167. {
  168. HKEY hkey;
  169. DWORD dwError;
  170. BOOL fReturn = TRUE;
  171. LPWSTR pszK;
  172. *ppIpSec = NULL;
  173. if ( (pszK = (LPWSTR)LocalAlloc(LMEM_FIXED, (wcslen(pszRegKey)+wcslen(pszRegSubKey)+2)*sizeof(WCHAR))) == NULL )
  174. {
  175. return FALSE;
  176. }
  177. wcscpy( pszK, pszRegKey );
  178. wcscat( pszK, L"\\" );
  179. wcscat( pszK, pszRegSubKey );
  180. dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
  181. pszK,
  182. 0,
  183. KEY_ALL_ACCESS,
  184. &hkey );
  185. LocalFree( pszK );
  186. if ( dwError != NO_ERROR) {
  187. if ( dwError != ERROR_FILE_NOT_FOUND ) {
  188. // maybe access denied or some other error.
  189. SetLastError( dwError );
  190. return (FALSE);
  191. }
  192. //
  193. // A non-existent key is the same as a blank key
  194. //
  195. } else {
  196. CHAR * psz;
  197. CHAR * pszTmp;
  198. DWORD cb;
  199. DWORD cEntries = 0;
  200. INETA_IP_SEC_LIST * pIPSec = NULL;
  201. psz = pszTmp = KludgeMultiSz( hkey, &cb );
  202. RegCloseKey( hkey );
  203. //
  204. // Count the number of addresses and then add them to the list
  205. //
  206. if ( psz != NULL ) {
  207. for( ; *pszTmp; cEntries++ ) {
  208. pszTmp += strlen( pszTmp ) + 1;
  209. }
  210. pszTmp = psz;
  211. if ( cEntries > 0) {
  212. pIPSec = ((INETA_IP_SEC_LIST *)
  213. LocalAlloc( LMEM_FIXED,
  214. sizeof(INETA_IP_SEC_LIST) +
  215. cEntries * sizeof(INETA_IP_SEC_ENTRY ))
  216. );
  217. if ( pIPSec == NULL ) {
  218. dwError = ERROR_NOT_ENOUGH_MEMORY;
  219. fReturn = FALSE;
  220. } else {
  221. for( pIPSec->cEntries = 0;
  222. *pszTmp;
  223. pszTmp += strlen( pszTmp ) + 1
  224. ) {
  225. if (!DottedDecimalToDword( &pszTmp,
  226. &pIPSec->aIPSecEntry[pIPSec->cEntries].dwMask ) ||
  227. !DottedDecimalToDword( &pszTmp,
  228. &pIPSec->aIPSecEntry[pIPSec->cEntries].dwNetwork )
  229. ) {
  230. } else {
  231. pIPSec->cEntries++;
  232. }
  233. } // for
  234. dwError = NO_ERROR;
  235. }
  236. }
  237. if ( dwError == NO_ERROR) {
  238. *ppIpSec = pIPSec;
  239. }
  240. LocalFree( psz );
  241. }
  242. if ( !fReturn) {
  243. SetLastError( dwError);
  244. }
  245. }
  246. return ( fReturn);
  247. } // IPAccessList::ReadIPList()
  248. BOOL
  249. DottedDecimalToDword(
  250. CHAR * * ppszAddress,
  251. DWORD * pdwAddress )
  252. /*++
  253. Routine Description:
  254. Converts a dotted decimal IP string to it's network equivalent
  255. Note: White space is eaten before *pszAddress and pszAddress is set
  256. to the character following the converted address
  257. Arguments:
  258. ppszAddress - Pointer to address to convert. White space before the
  259. address is OK. Will be changed to point to the first character after
  260. the address
  261. pdwAddress - DWORD equivalent address in network order
  262. returns TRUE if successful, FALSE if the address is not correct
  263. --*/
  264. {
  265. CHAR * psz;
  266. USHORT i;
  267. ULONG value;
  268. int iSum =0;
  269. ULONG k = 0;
  270. UCHAR Chr;
  271. UCHAR pArray[4];
  272. psz = *ppszAddress;
  273. //
  274. // Skip white space
  275. //
  276. while ( *psz && !isdigit( (UCHAR)(*psz) ))
  277. psz++;
  278. //
  279. // Convert the four segments
  280. //
  281. pArray[0] = 0;
  282. while ((Chr = *psz) && (Chr != ' ') )
  283. {
  284. if (Chr == '.')
  285. {
  286. // be sure not to overflow a byte.
  287. if (iSum <= 0xFF)
  288. pArray[k] = (UCHAR)iSum;
  289. else
  290. return FALSE;
  291. // check for too many periods in the address
  292. if (++k > 3)
  293. return FALSE;
  294. pArray[k] = 0;
  295. iSum = 0;
  296. }
  297. else
  298. {
  299. Chr = Chr - '0';
  300. // be sure character is a number 0..9
  301. if ((Chr < 0) || (Chr > 9))
  302. return FALSE;
  303. iSum = iSum*10 + Chr;
  304. }
  305. psz++;
  306. }
  307. // save the last sum in the byte and be sure there are 4 pieces to the
  308. // address
  309. if ((iSum <= 0xFF) && (k == 3))
  310. pArray[k] = (UCHAR)iSum;
  311. else
  312. return FALSE;
  313. // now convert to a ULONG, in network order...
  314. value = 0;
  315. // go through the array of bytes and concatenate into a ULONG
  316. for (i=0; i < 4; i++ )
  317. {
  318. value = (value << 8) + pArray[i];
  319. }
  320. *pdwAddress = htonl( value );
  321. *ppszAddress = psz;
  322. return TRUE;
  323. }
  324. BOOL
  325. FillAddrCheckFromIpList(
  326. BOOL fIsGrant,
  327. LPINET_INFO_IP_SEC_LIST pInfo,
  328. ADDRESS_CHECK *pCheck
  329. )
  330. /*++
  331. Routine Description:
  332. Fill an access check object from an IP address list from
  333. Arguments:
  334. fIsGrant - TRUE to access grant list, FALSE to access deny list
  335. pInfo - ptr to IP address list
  336. pCheck - ptr to address check object to update
  337. Return:
  338. TRUE if success, otherwise FALSE
  339. --*/
  340. {
  341. UINT x;
  342. if ( pInfo )
  343. {
  344. for ( x = 0 ; x < pInfo->cEntries ; ++x )
  345. {
  346. if ( ! pCheck->AddAddr( fIsGrant,
  347. AF_INET,
  348. (LPBYTE)&pInfo->aIPSecEntry[x].dwMask,
  349. (LPBYTE)&pInfo->aIPSecEntry[x].dwNetwork ) )
  350. {
  351. return FALSE;
  352. }
  353. }
  354. }
  355. return TRUE;
  356. }
  357. DWORD
  358. MigrateServiceIpSec(
  359. LPWSTR pszSrvRegKey,
  360. LPWSTR pszSrvMetabasePath
  361. )
  362. {
  363. INETA_IP_SEC_LIST* pGrant = NULL;
  364. INETA_IP_SEC_LIST* pDeny = NULL;
  365. ADDRESS_CHECK acCheck;
  366. DWORD err = 0;
  367. if ( ReadIPList( pszSrvRegKey, IPSEC_GRANT_LIST, &pGrant ) &&
  368. ReadIPList( pszSrvRegKey, IPSEC_DENY_LIST, &pDeny ) )
  369. {
  370. if ( pGrant || pDeny )
  371. {
  372. acCheck.BindCheckList( NULL, 0 );
  373. if ( FillAddrCheckFromIpList( TRUE, pGrant, &acCheck ) &&
  374. FillAddrCheckFromIpList( FALSE, pDeny, &acCheck ) )
  375. {
  376. CMDKey cmdKey;
  377. cmdKey.OpenNode(pszSrvMetabasePath);
  378. if ( (METADATA_HANDLE)cmdKey ) {
  379. cmdKey.SetData(
  380. MD_IP_SEC,
  381. METADATA_INHERIT | METADATA_REFERENCE,
  382. IIS_MD_UT_FILE,
  383. BINARY_METADATA,
  384. acCheck.GetStorage()->GetUsed(),
  385. (acCheck.GetStorage()->GetAlloc()
  386. ? acCheck.GetStorage()->GetAlloc() : (LPBYTE)"")
  387. );
  388. cmdKey.Close();
  389. }
  390. }
  391. }
  392. acCheck.UnbindCheckList();
  393. }
  394. else
  395. {
  396. err = GetLastError();
  397. }
  398. if ( pGrant )
  399. {
  400. LocalFree( pGrant );
  401. }
  402. if ( pDeny )
  403. {
  404. LocalFree( pDeny );
  405. }
  406. return err;
  407. }
  408. VOID SetLocalHostRestriction(LPCTSTR szKeyPath)
  409. {
  410. DWORD dwReturn = 0;
  411. ADDRESS_CHECK acCheck;
  412. iisDebugOut_Start1(_T("SetLocalHostRestriction"), (LPTSTR) szKeyPath, LOG_TYPE_TRACE);
  413. acCheck.BindCheckList( NULL, 0 );
  414. acCheck.AddAddr(TRUE, AF_INET, (LPBYTE)"\xff\xff\xff\xff", (LPBYTE)"\x7f\x0\x0\x1");
  415. MDEntry stMDEntry;
  416. stMDEntry.szMDPath = (LPTSTR)(LPCTSTR)szKeyPath;
  417. stMDEntry.dwMDIdentifier = MD_IP_SEC;
  418. stMDEntry.dwMDAttributes = METADATA_INHERIT | METADATA_REFERENCE;
  419. stMDEntry.dwMDUserType = IIS_MD_UT_FILE;
  420. stMDEntry.dwMDDataType = BINARY_METADATA;
  421. stMDEntry.dwMDDataLen = acCheck.GetStorage()->GetUsed();
  422. if (acCheck.GetStorage()->GetAlloc())
  423. {
  424. stMDEntry.pbMDData = (LPBYTE) acCheck.GetStorage()->GetAlloc();
  425. dwReturn = SetMDEntry_Wrap(&stMDEntry);
  426. }
  427. else
  428. {
  429. stMDEntry.pbMDData = (LPBYTE) "";
  430. int iBeforeValue = FALSE;
  431. iBeforeValue = g_CheckIfMetabaseValueWasWritten;
  432. g_CheckIfMetabaseValueWasWritten = FALSE;
  433. dwReturn = SetMDEntry_Wrap(&stMDEntry);
  434. // Set the flag back after calling the function
  435. g_CheckIfMetabaseValueWasWritten = iBeforeValue;
  436. }
  437. /*
  438. CMDKey cmdKey;
  439. cmdKey.OpenNode(szKeyPath);
  440. if ( (METADATA_HANDLE)cmdKey )
  441. {
  442. cmdKey.SetData(MD_IP_SEC,METADATA_INHERIT | METADATA_REFERENCE,IIS_MD_UT_FILE,BINARY_METADATA,acCheck.GetStorage()->GetUsed(),(acCheck.GetStorage()->GetAlloc()? acCheck.GetStorage()->GetAlloc() : (LPBYTE)"") );
  443. cmdKey.Close();
  444. }
  445. */
  446. acCheck.UnbindCheckList();
  447. iisDebugOut_End1(_T("SetLocalHostRestriction"), (LPTSTR) szKeyPath, LOG_TYPE_TRACE);
  448. return;
  449. }
  450. DWORD SetIISADMINRestriction(LPCTSTR szKeyPath)
  451. {
  452. SetLocalHostRestriction(szKeyPath);
  453. return 0;
  454. }
  455. #endif //_CHICAGO_