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.

351 lines
11 KiB

  1. /*--
  2. Copyright (c) 1995-1998 Microsoft Corporation
  3. Module Name: REQUEST.H
  4. Author: Arul Menezes
  5. Abstract: HTTP request class
  6. --*/
  7. // Scalar types used by CHTTPRequest
  8. typedef enum {
  9. TOK_GET=1,
  10. TOK_HEAD,
  11. TOK_POST,
  12. TOK_UNKNOWN_VERB,
  13. TOK_DATE,
  14. TOK_PRAGMA,
  15. TOK_COOKIE,
  16. TOK_ACCEPT,
  17. TOK_REFERER,
  18. TOK_UAGENT,
  19. TOK_AUTH,
  20. TOK_IFMOD,
  21. TOK_TYPE,
  22. TOK_LENGTH,
  23. TOK_ENCODING,
  24. TOK_CONNECTION,
  25. }
  26. TOKEN;
  27. typedef enum
  28. {
  29. CONN_NONE = 0,
  30. CONN_CLOSE = 1,
  31. CONN_KEEP = 2,
  32. }
  33. CONNHEADER;
  34. #define CHTTPREQUEST_SIG 0xAB0D
  35. // This object is the top-level object for an incoming HTTP request. One such object
  36. // is created per request & a thread is created to handle it.
  37. class CFilterInfo;
  38. class CHttpRequest
  39. {
  40. // socket
  41. DWORD m_dwSig;
  42. SOCKET m_socket;
  43. // buffers
  44. CBuffer m_bufRequest;
  45. CBuffer m_bufRespBody;
  46. // method, version, URL etc. Direct results of parse
  47. PSTR m_pszMethod;
  48. PSTR m_pszURL;
  49. PSTR m_pszContentType;
  50. DWORD m_dwContentLength;
  51. PSTR m_pszAccept;
  52. FILETIME m_ftIfModifiedSince;
  53. DWORD m_dwIfModifiedLength;
  54. BOOL m_fKeepAlive;
  55. PSTR m_pszCookie;
  56. // Decoded URL (indirect results of parse)
  57. PSTR m_pszQueryString;
  58. PWSTR m_wszPath;
  59. PWSTR m_wszExt;
  60. PSTR m_pszPathInfo;
  61. PSTR m_pszPathTranslated;
  62. // VRoot information
  63. SCRIPT_TYPE m_VRootScriptType;
  64. DWORD m_dwPermissions;
  65. AUTHLEVEL m_AuthLevelReqd;
  66. // Logging members
  67. PSTR m_pszLogParam;
  68. RESPONSESTATUS m_rs;
  69. BOOL m_fBufferedResponse; // Are we using m_bufResponse or sending straight to client?
  70. // Async support
  71. HANDLE m_hEvent;
  72. DWORD m_dwStatus;
  73. LPEXTENSION_CONTROL_BLOCK m_pECB;
  74. PVOID m_pvContext;
  75. PFN_HSE_IO_COMPLETION m_pfnCompletion;
  76. // Parsing functions
  77. void FreeHeaders(void)
  78. {
  79. MyFree(m_pszMethod);
  80. MyFree(m_pszURL);
  81. MyFree(m_pszContentType);
  82. MyFree(m_pszAccept);
  83. MyFree(m_pszQueryString);
  84. MyFree(m_wszPath);
  85. MyFree(m_wszExt);
  86. MyFree(m_pszCookie);
  87. MyFree(m_pszLogParam);
  88. MyFree(m_pszPathInfo);
  89. MyFree(m_pszPathTranslated);
  90. }
  91. BOOL ParseHeaders();
  92. BOOL MyCrackURL(PSTR pszRawURL, int iLen);
  93. public:
  94. BOOL ParseMethod(PCSTR pszMethod, int cbMethod);
  95. BOOL ParseContentLength(PCSTR pszMethod, TOKEN id);
  96. BOOL ParseContentType(PCSTR pszMethod, TOKEN id);
  97. BOOL ParseIfModifiedSince(PCSTR pszMethod, TOKEN id);
  98. BOOL ParseAuthorization(PCSTR pszMethod, TOKEN id);
  99. BOOL ParseAccept(PCSTR pszMethod, TOKEN id);
  100. BOOL ParseConnection(PCSTR pszMethod, TOKEN id);
  101. BOOL ParseCookie(PCSTR pszMethod, TOKEN id);
  102. BOOL HandleNTLMAuth(PSTR pszNTLMData);
  103. PSTR m_pszNTLMOutBuf; // buffer to send client on NTLM response, Base64 encoded
  104. DWORD m_dwVersion; // LOWORD=minor, HIWORD=major.
  105. TOKEN m_idMethod;
  106. CBuffer m_bufRespHeaders;
  107. CFilterInfo *m_pFInfo; // Filter state information
  108. private:
  109. // Authentication data members
  110. AUTHLEVEL m_AuthLevelGranted;
  111. PSTR m_pszAuthType;
  112. PSTR m_pszRawRemoteUser; // Holds base64 encoded data, before auth decodes it
  113. PSTR m_pszRemoteUser;
  114. PSTR m_pszPassword;
  115. AUTH_NTLM m_NTLMState; // state info for NTLM process, needs to be saved across requests
  116. DWORD m_dwAuthFlags;
  117. WCHAR *m_wszVRootUserList; // Do NOT free this, points to global mem. Contains user/group ACL
  118. // Authentication functions
  119. void FreeAuth(void)
  120. {
  121. MyFree(m_pszAuthType);
  122. MyFree(m_pszRawRemoteUser);
  123. MyFree(m_pszRemoteUser);
  124. MyFree(m_pszPassword);
  125. MyFree(m_pszNTLMOutBuf);
  126. // Don't free NTLM structs in here
  127. }
  128. BOOL CheckAuth(AUTHLEVEL AuthLevelReqd)
  129. {
  130. return ( (AuthLevelReqd <= m_AuthLevelGranted));
  131. }
  132. BOOL CheckAuth() { return CheckAuth(m_AuthLevelReqd); }
  133. // File GET/HEAD handling functions
  134. BOOL IsNotModified(HANDLE hFile, DWORD dwLength);
  135. static RESPONSESTATUS GLEtoStatus(int iGLE);
  136. // Directory: Default page & browsing functions
  137. BOOL MapDirToDefaultPage(void);
  138. BOOL EmitDirListing(void);
  139. void Init();
  140. BOOL ReadPostData(DWORD dwMaxSizeToRead, BOOL fInitialPostRead);
  141. CONNHEADER GetConnHeader() { return m_fKeepAlive ? CONN_KEEP : CONN_CLOSE; }
  142. // ISAPI extension handling functions
  143. BOOL HandleScript();
  144. BOOL ExecuteISAPI(void);
  145. void FillECB(LPEXTENSION_CONTROL_BLOCK pECB);
  146. BOOL GetServerVariable(PSTR pszVar, PVOID pvOutBuf, PDWORD pdwOutSize, BOOL fFromFilter);
  147. BOOL WriteClient(PVOID pvBuf, PDWORD pdwSize, BOOL fFromFilter);
  148. BOOL WriteClientAsync(PVOID pvBuf, PDWORD pdwSize, BOOL fFromFilter);
  149. BOOL ServerSupportFunction(DWORD dwReq, PVOID pvBuf, PDWORD pdwSize, PDWORD pdwType);
  150. BOOL ReadClient(PVOID pv, PDWORD pdw);
  151. void StartRemoveISAPICacheIfNeeded();
  152. // Filter Specific
  153. BOOL FillFC(PHTTP_FILTER_CONTEXT pfc, DWORD dwNotifyType,
  154. LPVOID *ppStFilter, LPVOID *ppStFilterOrg,
  155. PSTR *ppvBuf1, int *pcbBuf, PSTR *ppvBuf2, int *pcbBuf2);
  156. void CleanupFC(DWORD dwNotifyType, LPVOID* pFilterStruct, LPVOID *pFilterStructOrg,
  157. PSTR *ppvBuf1, int *pcbBuf, PSTR *ppvBuf2);
  158. BOOL AuthenticateFilter();
  159. BOOL FilterMapURL(PSTR pvBuf, WCHAR *wszPath, DWORD *pdwSize, DWORD dwBufNeeded, PSTR pszURLEx=NULL);
  160. BOOL MapURLToPath(PSTR pszBuffer, PDWORD pdwSize, LPHSE_URL_MAPEX_INFO pUrlMapEx=NULL);
  161. // Filter Callbacks
  162. BOOL ServerSupportFunction(enum SF_REQ_TYPE sfReq,PVOID pData,ULONG_PTR ul1, ULONG_PTR ul2);
  163. BOOL GetHeader(LPSTR lpszName, LPVOID lpvBuffer, LPDWORD lpdwSize);
  164. BOOL SetHeader(LPSTR lpszName, LPSTR lpszValue);
  165. BOOL AddResponseHeaders(LPSTR lpszHeaders,DWORD dwReserved);
  166. // ASP Setup Fcns
  167. BOOL ExecuteASP();
  168. BOOL FillACB(void *p, HINSTANCE hInst);
  169. public:
  170. CHttpRequest(SOCKET sock)
  171. {
  172. Init();
  173. m_socket = sock;
  174. // Fixes BUG 11771. On a poorly formatted request line, if we didn't
  175. // read in the http version right we assumed it's value was 0, since 0 < 1.0
  176. // we'd treat this as a http/0.9 request, no headers would be sent.
  177. m_dwVersion = MAKELONG(0,1);
  178. }
  179. ~CHttpRequest();
  180. BOOL ReInit();
  181. void HandleRequest();
  182. friend DWORD WINAPI HttpConnectionThread(LPVOID lpv);
  183. void GenerateLog(PSTR szBuffer, DWORD_PTR *pdwToWrite);
  184. // BOOL SetupHeader(PSTR *ppszHeader, int *piHeader, PSTR *ppszExtra, int *piExtra, BOOL fAccessDenied);
  185. DWORD GetLogBufferSize();
  186. // ISAPI Extension / ASP Specific
  187. friend BOOL WINAPI GetServerVariable(HCONN hConn, PSTR psz, PVOID pv, PDWORD pdw);
  188. friend BOOL WINAPI ReadClient(HCONN hConn, PVOID pv, PDWORD pdw);
  189. friend BOOL WINAPI WriteClient(HCONN hConn, PVOID pv, PDWORD pdw, DWORD dw);
  190. friend BOOL WINAPI ServerSupportFunction(HCONN hConn, DWORD dwReq, PVOID pvBuf, PDWORD pdwSize, PDWORD pdwType);
  191. // ASP SPECIFIC
  192. friend BOOL WINAPI Flush(HCONN hConn);
  193. friend BOOL WINAPI Clear(HCONN hConn);
  194. friend BOOL WINAPI SetBuffer(HCONN hConn, BOOL fBuffer);
  195. friend BOOL WINAPI AddHeader (HCONN hConn, LPSTR lpszName, LPSTR lpszValue);
  196. // FILTER SPECIFIC
  197. BOOL CallFilter(DWORD dwNotifyType, PSTR *ppvBuf1 = NULL,int *pcbBuf = NULL,
  198. PSTR *ppvBuf2 = NULL, int *pcbBuf2 = NULL);
  199. BOOL FilterNoResponse(void);
  200. // Filters Friends (exposed to Filter dll)
  201. friend BOOL WINAPI GetServerVariable(PHTTP_FILTER_CONTEXT pfc, PSTR psz, PVOID pv, PDWORD pdw);
  202. friend BOOL WINAPI AddResponseHeaders(PHTTP_FILTER_CONTEXT pfc,LPSTR lpszHeaders,DWORD dwReserved);
  203. friend VOID* WINAPI AllocMem(PHTTP_FILTER_CONTEXT pfc, DWORD cbSize, DWORD dwReserved);
  204. friend BOOL WINAPI WriteClient(PHTTP_FILTER_CONTEXT pfc, PVOID pv, PDWORD pdw, DWORD dwFlags);
  205. friend BOOL WINAPI ServerSupportFunction(PHTTP_FILTER_CONTEXT pfc,enum SF_REQ_TYPE sfReq,
  206. PVOID pData, ULONG_PTR ul1, ULONG_PTR ul2);
  207. friend BOOL WINAPI SetHeader(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszName, LPSTR lpszValue);
  208. friend BOOL WINAPI GetHeader(PHTTP_FILTER_CONTEXT pfc, LPSTR lpszName, LPVOID lpvBuffer, LPDWORD lpdwSize);
  209. };
  210. void SendFile(SOCKET sock, HANDLE hFile, CHttpRequest *pRequest);
  211. // Response object. This object doesn't own any of the handles or pointers
  212. // it uses so it doesnt free anything. The caller is responsible in all cases
  213. // for keeping the handles & memory alive while this object is extant & freeing
  214. // them as approp at a later time
  215. class CHttpResponse
  216. {
  217. SOCKET m_socket;
  218. RESPONSESTATUS m_rs;
  219. CONNHEADER m_connhdr;
  220. PCSTR m_pszType;
  221. DWORD m_dwLength;
  222. PCSTR m_pszRedirect;
  223. PCSTR m_pszExtraHeaders;
  224. PCSTR m_pszBody;
  225. HANDLE m_hFile;
  226. char m_szMime[MAXMIME];
  227. CHttpRequest *m_pRequest; // calling request class, for callbacks
  228. private:
  229. void SetTypeFromExtW(PCWSTR wszExt)
  230. {
  231. DEBUGCHK(!m_pszType);
  232. m_szMime[0] = 0;
  233. if(wszExt)
  234. {
  235. CReg reg(HKEY_CLASSES_ROOT, wszExt);
  236. MyW2A(reg.ValueSZ(L"Content Type"), m_szMime, sizeof(m_szMime));
  237. }
  238. if(m_szMime[0])
  239. m_pszType = m_szMime;
  240. else
  241. m_pszType = cszTextHtml;
  242. }
  243. public:
  244. CHttpResponse(SOCKET sock, RESPONSESTATUS status, CONNHEADER connhdr, CHttpRequest *pRequest=NULL)
  245. {
  246. ZEROMEM(this);
  247. m_socket = sock;
  248. m_rs = status;
  249. m_connhdr = connhdr;
  250. m_pRequest = pRequest;
  251. }
  252. // for generated bodies (dir listings, redirects etc) & default bodies
  253. void SetBody(PCSTR pszBody, PCSTR pszType)
  254. {
  255. DEBUGCHK(!m_hFile && !m_pszBody && !m_pszType && !m_dwLength);
  256. m_pszType = pszType;
  257. m_dwLength = strlen(pszBody);
  258. m_pszBody = pszBody;
  259. }
  260. // for error reponses (NOTE: some have no body, and hence psztatusBdy will be NULL in the table)
  261. void SetDefaultBody()
  262. {
  263. if(rgStatus[m_rs].pszStatusBody)
  264. SetBody(rgStatus[m_rs].pszStatusBody, cszTextHtml);
  265. }
  266. // for real files
  267. void SetBody(HANDLE hFile, PCWSTR wszExt=NULL, DWORD dwLen=0)
  268. {
  269. DEBUGCHK(!m_hFile && !m_pszBody && !m_pszType && !m_dwLength);
  270. m_hFile = hFile;
  271. SetTypeFromExtW(wszExt);
  272. if (dwLen)
  273. m_dwLength = dwLen;
  274. else
  275. {
  276. m_dwLength = GetFileSize(m_hFile, 0);
  277. if (m_dwLength == 0)
  278. m_dwLength = -1; // Use this to signify empty file, needed for keep-alives
  279. }
  280. }
  281. private:
  282. void SendBody();
  283. public:
  284. void SendHeaders(PCSTR pszExtraHeaders, PCSTR pszNewRespStatus);
  285. void SendRedirect(PCSTR pszRedirect, BOOL fFromFilter=FALSE);
  286. void SendResponse(PCSTR pszExtraHeaders=NULL, PCSTR pszNewRespStatus=NULL, BOOL fFromFilter=FALSE)
  287. {
  288. // see FilterNoResponse for comments on this
  289. if (!fFromFilter && m_pRequest->FilterNoResponse())
  290. return;
  291. SendHeaders(pszExtraHeaders,pszNewRespStatus);
  292. SendBody();
  293. }
  294. };