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.

439 lines
13 KiB

  1. /*++
  2. Copyright (c) 2001 Microsoft Corporation
  3. Module Name :
  4. updateini.cpp
  5. Abstract:
  6. High level function to update the ini with new values
  7. Author:
  8. Christopher Achille (cachille)
  9. Project:
  10. URLScan Update
  11. Revision History:
  12. March 2002: Created
  13. --*/
  14. #include "stdafx.h"
  15. #include "windows.h"
  16. #include "updateini.h"
  17. #include "parseini.h"
  18. sURLScan_Settings g_urlSettings[] =
  19. { { L"options",
  20. L"UseAllowVerbs",
  21. { L"UseAllowVerbs=1 ; If 1, use [AllowVerbs] section, else use the",
  22. L" ; [DenyVerbs] section.",
  23. L"",
  24. NULL }
  25. }, // UseAllowVerbs
  26. { L"options",
  27. L"UseAllowExtensions",
  28. { L"UseAllowExtensions=0 ; If 1, use [AllowExtensions] section, else use",
  29. L" ; the [DenyExtensions] section.",
  30. L"",
  31. NULL }
  32. }, // UseAllowExtensions
  33. { L"options",
  34. L"NormalizeUrlBeforeScan",
  35. { L"NormalizeUrlBeforeScan=1 ; If 1, canonicalize URL before processing.",
  36. L"",
  37. NULL }
  38. }, // NormalizeUrlBeforeScan
  39. { L"options",
  40. L"VerifyNormalization",
  41. { L"VerifyNormalization=1 ; If 1, canonicalize URL twice and reject request",
  42. L" ; if a change occurs.",
  43. NULL }
  44. }, // VerifyNormalization
  45. { L"options",
  46. L"AllowHighBitCharacters",
  47. { L"AllowHighBitCharacters=0 ; If 1, allow high bit (ie. UTF8 or MBCS)",
  48. L" ; characters in URL.",
  49. L"",
  50. NULL }
  51. }, // AllowHighBitCharacters
  52. { L"options",
  53. L"AllowDotInPath",
  54. { L"AllowDotInPath=0 ; If 1, allow dots that are not file extensions.",
  55. L"",
  56. NULL }
  57. }, // AllowDotInPath
  58. { L"options",
  59. L"RemoveServerHeader",
  60. { L"RemoveServerHeader=0 ; If 1, remove the 'Server' header from response.",
  61. L"",
  62. NULL }
  63. }, // RemoveServerHeader
  64. { L"options",
  65. L"EnableLogging",
  66. { L"EnableLogging=1 ; If 1, log UrlScan activity.",
  67. L"",
  68. NULL }
  69. }, // EnableLogging
  70. { L"options",
  71. L"PerProcessLogging",
  72. { L"PerProcessLogging=0 ; If 1, the UrlScan.log filename will contain a PID",
  73. L" ; (ie. UrlScan.123.log).",
  74. L"",
  75. NULL }
  76. }, // PerProcessLogging
  77. { L"options",
  78. L"AllowLateScanning",
  79. { L"AllowLateScanning=0 ; If 1, then UrlScan will load as a low priority",
  80. L" ; filter.",
  81. L"",
  82. NULL }
  83. }, // AllowLateScanning
  84. { L"options",
  85. L"PerDayLogging",
  86. { L"PerDayLogging=1 ; If 1, UrlScan will produce a new log each day with",
  87. L" ; activity in the form 'UrlScan.010101.log'.",
  88. L"",
  89. NULL }
  90. }, // PerDayLogging
  91. { L"options",
  92. L"UseFastPathReject",
  93. { L"UseFastPathReject=0 ; If 1, then UrlScan will not use the",
  94. L" ; RejectResponseUrl or allow IIS to log the request.",
  95. L"",
  96. NULL }
  97. }, // UseFastPathReject
  98. { L"options", // Section Name
  99. L"LogLongUrls", // Setting Name
  100. { L"LogLongUrls=0 ; If 1, then up to 128K per request can be logged.",
  101. L" ; If 0, then only 1k is allowed.",
  102. L"",
  103. NULL }
  104. }, // LogLongURLs
  105. { L"options",
  106. L"RejectResponseUrl",
  107. { L";",
  108. L"; If UseFastPathReject is 0, then UrlScan will send",
  109. L"; rejected requests to the URL specified by RejectResponseUrl.",
  110. L"; If not specified, '/<Rejected-by-UrlScan>' will be used.",
  111. L";",
  112. L"",
  113. L"RejectResponseUrl=",
  114. L"",
  115. NULL }
  116. }, // RejectResponseUrl
  117. { L"options",
  118. L"LoggingDirectory",
  119. { L";",
  120. L"; LoggingDirectory can be used to specify the directory where the",
  121. L"; log file will be created. This value should be the absolute path",
  122. L"; (ie. c:\\some\\path). If not specified, then UrlScan will create",
  123. L"; the log in the same directory where the UrlScan.dll file is located.",
  124. L";",
  125. L"",
  126. L"LoggingDirectory=",
  127. L"",
  128. NULL }
  129. }, // Logging Directory
  130. { L"options",
  131. L"AlternateServerName",
  132. { L";",
  133. L"; If RemoveServerHeader is 0, then AlternateServerName can be",
  134. L"; used to specify a replacement for IIS's built in 'Server' header",
  135. L";",
  136. L"",
  137. L"AlternateServerName=",
  138. L"",
  139. NULL }
  140. }, // AlternateServerName
  141. { L"RequestLimits",
  142. L"MaxUrl",
  143. { L"MaxUrl=16384",
  144. NULL }
  145. }, // MaxUrl
  146. { L"RequestLimits",
  147. L"MaxQueryString",
  148. { L"MaxQueryString=4096",
  149. NULL}
  150. }, // MaxQueryString
  151. { L"RequestLimits",
  152. L"MaxAllowedContentLength",
  153. #ifdef PLEASE_BUILD_LESS_AGRESSIVE_DEFAULTS_VERSION
  154. { L"MaxAllowedContentLength=2000000000",
  155. #else
  156. { L"MaxAllowedContentLength=30000000",
  157. #endif
  158. NULL }
  159. } // MaxAllowedContentLength
  160. };
  161. sURLScan_Sections g_urlSections[] =
  162. { { L"RequestLimits", // Section Name
  163. { L"",
  164. L";",
  165. L"; The entries in this section impose limits on the length",
  166. L"; of allowed parts of requests reaching the server.",
  167. L";",
  168. L"; It is possible to impose a limit on the length of the",
  169. L"; value of a specific request header by prepending \"Max-\" to the",
  170. L"; name of the header. For example, the following entry would",
  171. L"; impose a limit of 100 bytes to the value of the",
  172. L"; 'Content-Type' header:",
  173. L";",
  174. L"; Max-Content-Type=100",
  175. L";",
  176. L"; To list a header and not specify a maximum value, use 0",
  177. L"; (ie. 'Max-User-Agent=0'). Also, any headers not listed",
  178. L"; in this section will not be checked for length limits.",
  179. L";",
  180. L"; There are 3 special case limits:",
  181. L";",
  182. L"; - MaxAllowedContentLength specifies the maximum allowed",
  183. L"; numeric value of the Content-Length request header. For",
  184. L"; example, setting this to 1000 would cause any request",
  185. L"; with a content length that exceeds 1000 to be rejected.",
  186. #ifdef PLEASE_BUILD_LESS_AGRESSIVE_DEFAULTS_VERSION
  187. L"; The default is 2000000000.",
  188. #else
  189. L"; The default is 30000000.",
  190. #endif
  191. L";",
  192. L"; - MaxUrl specifies the maximum length of the request URL,",
  193. L"; not including the query string. The default is 260 (which",
  194. L"; is equivalent to MAX_PATH).",
  195. L";",
  196. L"; - MaxQueryString specifies the maximum length of the query",
  197. L"; string. The default is 4096.",
  198. L";",
  199. L"",
  200. #ifdef PLEASE_BUILD_LESS_AGRESSIVE_DEFAULTS_VERSION
  201. L"MaxAllowedContentLength=2000000000",
  202. #else
  203. L"MaxAllowedContentLength=30000000",
  204. #endif
  205. L"MaxUrl=16384",
  206. L"MaxQueryString=4096",
  207. L"",
  208. NULL }
  209. } // end of RequestLimits
  210. };
  211. sURLScan_Items g_urlItems[] =
  212. { { L"DenyHeaders",
  213. L"Transfer-Encoding:",
  214. { L"Transfer-Encoding:",
  215. NULL }
  216. }
  217. };
  218. // GetListLen
  219. //
  220. // Retrieve the Length of a variable length array of Strings
  221. // This is a special case function that works for our structs
  222. // above, because we leave the last String as NULL
  223. //
  224. DWORD GetListLen(LPWSTR szLines[])
  225. {
  226. DWORD dwLen = 0;
  227. while ( szLines[dwLen] != NULL )
  228. {
  229. dwLen++;
  230. }
  231. return dwLen;
  232. }
  233. // GetIniPath
  234. //
  235. // Given the Path to the Dll, create the path to the ini
  236. //
  237. // Parameters:
  238. // szDllPath - [in] The path to the binary for urlscan.dll
  239. // szIniPath - [out] The path to the ini file
  240. // dwIniLen - [in] The length of the string passed in for szIniPath
  241. //
  242. BOOL GetIniPath( LPTSTR szDllPath, LPTSTR szIniPath, DWORD dwIniLen )
  243. {
  244. LPTSTR szLastPeriod;
  245. if ( _tcslen( szDllPath ) >= ( dwIniLen - 3 ) )
  246. {
  247. // Error, string is not big enough
  248. return FALSE;
  249. }
  250. _tcscpy( szIniPath, szDllPath);
  251. szLastPeriod = _tcsrchr( szIniPath, '.' );
  252. if ( !szLastPeriod )
  253. {
  254. // Can not find the extension
  255. return FALSE;
  256. }
  257. _tcscpy( szLastPeriod, URLSCAN_INI_EXTENSION );
  258. return TRUE;
  259. }
  260. // UpdateIniSections
  261. //
  262. // Update the Sections in the Ini, by merging them with the ones we have
  263. // defined
  264. //
  265. BOOL UpdateIniSections( CIniFile *pURLScanIniFile )
  266. {
  267. DWORD dwCurrentSection;
  268. for ( dwCurrentSection = 0;
  269. dwCurrentSection < ( (DWORD) sizeof( g_urlSections ) / sizeof ( sURLScan_Sections ) );
  270. dwCurrentSection++)
  271. {
  272. if ( !pURLScanIniFile->DoesSectionExist( g_urlSections[ dwCurrentSection].szSection ) )
  273. {
  274. // Try to Create Section Then
  275. if ( !pURLScanIniFile->AddSection( g_urlSections[dwCurrentSection].szSection ) )
  276. {
  277. // Failed to Add Section
  278. return FALSE;
  279. }
  280. // Now try to add the correct lines to it
  281. if ( g_urlSections[dwCurrentSection].szLines &&
  282. !pURLScanIniFile->AddLinesToSection( g_urlSections[dwCurrentSection].szSection,
  283. GetListLen( g_urlSections[dwCurrentSection].szLines ),
  284. g_urlSections[dwCurrentSection].szLines ) )
  285. {
  286. // Failed to Add Lines
  287. return FALSE;
  288. }
  289. }
  290. }
  291. return TRUE;
  292. }
  293. // UpdateIniSettings
  294. //
  295. // Update the Ini Settings inside the different sections if they are
  296. // not already set
  297. //
  298. BOOL UpdateIniSettings( CIniFile *pURLScanIniFile )
  299. {
  300. DWORD dwCurrentSettings;
  301. for ( dwCurrentSettings = 0;
  302. dwCurrentSettings < ( (DWORD) sizeof( g_urlSettings ) / sizeof ( sURLScan_Settings ) );
  303. dwCurrentSettings++)
  304. {
  305. if ( !pURLScanIniFile->DoesSectionExist( g_urlSettings[ dwCurrentSettings].szSection ) )
  306. {
  307. // Create Section Since it does not exist
  308. if ( !pURLScanIniFile->AddSection( g_urlSettings[dwCurrentSettings].szSection ) )
  309. {
  310. return FALSE;
  311. }
  312. } // !pURLScanIniFile->DoesSectionExist
  313. if ( !pURLScanIniFile->DoesSettingInSectionExist( g_urlSettings[dwCurrentSettings].szSection,
  314. g_urlSettings[dwCurrentSettings].szSettingName ) )
  315. {
  316. // This setting does not exist, so lets add it
  317. if ( !pURLScanIniFile->AddLinesToSection( g_urlSettings[dwCurrentSettings].szSection,
  318. GetListLen( g_urlSettings[dwCurrentSettings].szLines ),
  319. g_urlSettings[dwCurrentSettings].szLines ) )
  320. {
  321. return FALSE;
  322. }
  323. } // !pURLScanIniFile->DoesSettingInSectionExist
  324. }
  325. return TRUE;
  326. }
  327. // UpdateIniItems
  328. //
  329. // Update the Ini Settings inside the different sections if they are
  330. // not already set
  331. //
  332. BOOL UpdateIniItems( CIniFile *pURLScanIniFile )
  333. {
  334. DWORD dwCurrentItems;
  335. for ( dwCurrentItems = 0;
  336. dwCurrentItems < ( (DWORD) sizeof( g_urlItems ) / sizeof ( sURLScan_Items ) );
  337. dwCurrentItems++)
  338. {
  339. if ( !pURLScanIniFile->DoesSectionExist( g_urlItems[ dwCurrentItems].szSection ) )
  340. {
  341. // Create Section Since it does not exist
  342. if ( !pURLScanIniFile->AddSection( g_urlSettings[dwCurrentItems].szSection ) )
  343. {
  344. return FALSE;
  345. }
  346. } // !pURLScanIniFile->DoesSectionExist
  347. if ( !pURLScanIniFile->DoesItemInSectionExist( g_urlItems[dwCurrentItems].szSection,
  348. g_urlItems[dwCurrentItems].szSettingName ) )
  349. {
  350. // This setting does not exist, so lets add it
  351. if ( !pURLScanIniFile->AddLinesToSection( g_urlItems[dwCurrentItems].szSection,
  352. GetListLen( g_urlItems[dwCurrentItems].szLines ),
  353. g_urlItems[dwCurrentItems].szLines ) )
  354. {
  355. return FALSE;
  356. }
  357. } // !pURLScanIniFile->DoesItemInSectionExist
  358. }
  359. return TRUE;
  360. }
  361. // UpdateIni File
  362. //
  363. // Update the inf file with the new features
  364. //
  365. BOOL UpdateIni( LPTSTR szUrlScanPath )
  366. {
  367. CIniFile URLScanIniFile;
  368. TCHAR szIniLocation[MAX_PATH];
  369. BOOL bRet = TRUE;
  370. if ( !GetIniPath( szUrlScanPath, szIniLocation, MAX_PATH ) ||
  371. !URLScanIniFile.LoadFile( szIniLocation ) )
  372. {
  373. // Either we couldn't determine the location, or we couldn't
  374. // load the file
  375. return FALSE;
  376. }
  377. if ( bRet )
  378. {
  379. // Note: UpdateIniSections must come before UpdateIniSettings
  380. #ifdef PLEASE_BUILD_LESS_AGRESSIVE_DEFAULTS_VERSION
  381. bRet = UpdateIniSections( &URLScanIniFile ) &&
  382. UpdateIniSettings( &URLScanIniFile );
  383. #else
  384. bRet = UpdateIniSections( &URLScanIniFile ) &&
  385. UpdateIniSettings( &URLScanIniFile ) &&
  386. UpdateIniItems( &URLScanIniFile );
  387. #endif
  388. }
  389. if ( bRet )
  390. {
  391. // Everything so far so good, so lets write the new ini
  392. bRet = URLScanIniFile.SaveFile( szIniLocation );
  393. }
  394. return bRet;
  395. }