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.

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