//////////////////////////////////////////////////////////////////////////////////////////// /// Reads and parses the HTTP hedaer data from the SOCKET /// \param strError Output error string. /// \param pClientSocket the socket to read /// \return True if success, false if fail. //////////////////////////////////////////////////////////////////////////////////////////// HTTP_REQUEST_RESULT HTTPRequestHeader::ReadWebRequest(string& strError, NetSocket* pClientSocket) { gtSize_t nRead = 0; // The header will fit within this buffer. char readBuffer[COMM_BUFFER_SIZE]; // clear the memory. ZeroMemory(readBuffer, COMM_BUFFER_SIZE); // Read up to a buffer size worth of data. The function will detect the end of the header and will not read any more data. nRead = SocketReadHeader(pClientSocket, readBuffer, COMM_BUFFER_SIZE); // Check for error if (nRead == 0) { strError = "HTTPRequestHeader: SocketReadHeader read 0 bytes."; return HTTP_SOCKET_ERROR; } // Check for error if (nRead == (gtSize_t) - 1) { strError = "HTTPRequestHeader: SocketReadHeader read -1 bytes."; return HTTP_SOCKET_ERROR; } // Terminate the string readBuffer[nRead] = '\0'; // Parse the data we just read in and populate our own internal data fields. bool bRes = ExtractHeaderData(&readBuffer[0]); // Return early if error if (bRes == false) { strError = "HTTPRequestHeader: ExtractHeaderData failed."; return HTTP_PARSE_ERROR; } // Check to see if POST data is present. if (GetPostDataSize() > 0) { // Read the POST data bRes = ReadPostData(strError, pClientSocket); if (bRes == false) { strError = "HTTPRequestHeader: ReadPostData failed."; return HTTP_PARSE_ERROR; } } return HTTP_NO_ERROR; }
/* * Entry point for WebCit transaction */ void session_loop(void) { int xhttp; StrBuf *Buf; /* * We stuff these with the values coming from the client cookies, * so we can use them to reconnect a timed out session if we have to. */ wcsession *WCC; WCC= WC; WCC->upload_length = 0; WCC->upload = NULL; WCC->Hdr->nWildfireHeaders = 0; if (WCC->Hdr->HR.ContentLength > 0) { if (ReadPostData() < 0) { return; } } Buf = NewStrBuf(); WCC->trailing_javascript = NewStrBuf(); /* Convert base64-encoded URL's back to plain text */ if (!strncmp(ChrPtr(WCC->Hdr->this_page), "/B64", 4)) { StrBufCutLeft(WCC->Hdr->this_page, 4); StrBufDecodeBase64(WCC->Hdr->this_page); http_redirect(ChrPtr(WCC->Hdr->this_page)); goto SKIP_ALL_THIS_CRAP; } /* If there are variables in the URL, we must grab them now */ if (WCC->Hdr->PlainArgs != NULL) ParseURLParams(WCC->Hdr->PlainArgs); /* If the client sent a nonce that is incorrect, kill the request. */ if (havebstr("nonce")) { if (verbose) syslog(LOG_DEBUG, "Comparing supplied nonce %s to session nonce %d", bstr("nonce"), WCC->nonce ); if (ibstr("nonce") != WCC->nonce) { syslog(LOG_INFO, "Ignoring request with mismatched nonce."); hprintf("HTTP/1.1 404 Security check failed\r\n"); hprintf("Content-Type: text/plain\r\n"); begin_burst(); wc_printf("Security check failed.\r\n"); end_burst(); goto SKIP_ALL_THIS_CRAP; } } /* * If we're not connected to a Citadel server, try to hook up the connection now. */ if (!WCC->connected) { if (GetConnected()) { hprintf("HTTP/1.1 503 Service Unavailable\r\n"); hprintf("Content-Type: text/html\r\n"); begin_burst(); wc_printf("<html><head><title>503 Service Unavailable</title></head><body>\n"); wc_printf(_("This program was unable to connect or stay " "connected to the Citadel server. Please report " "this problem to your system administrator.") ); wc_printf("<br>"); wc_printf("<a href=\"http://www.citadel.org/doku.php/" "faq:generalquestions:webcit_unable_to_connect\">%s</a>", _("Read More...") ); wc_printf("</body></html>\n"); end_burst(); goto SKIP_ALL_THIS_CRAP; } } /* * If we're not logged in, but we have authentication data (either from * a cookie or from http-auth), try logging in to Citadel using that. */ if ( (!WCC->logged_in) && (StrLength(WCC->Hdr->c_username) > 0) && (StrLength(WCC->Hdr->c_password) > 0) ) { long Status; FlushStrBuf(Buf); serv_printf("USER %s", ChrPtr(WCC->Hdr->c_username)); StrBuf_ServGetln(Buf); if (GetServerStatus(Buf, &Status) == 3) { serv_printf("PASS %s", ChrPtr(WCC->Hdr->c_password)); StrBuf_ServGetln(Buf); if (GetServerStatus(Buf, NULL) == 2) { become_logged_in(WCC->Hdr->c_username, WCC->Hdr->c_password, Buf); } else { /* Should only display when password is wrong */ WCC->ImportantMsg = NewStrBufPlain(ChrPtr(Buf) + 4, StrLength(Buf) - 4); authorization_required(); FreeStrBuf(&Buf); goto SKIP_ALL_THIS_CRAP; } } else if (Status == 541) { WCC->logged_in = 1; } } xhttp = (WCC->Hdr->HR.eReqType != eGET) && (WCC->Hdr->HR.eReqType != ePOST) && (WCC->Hdr->HR.eReqType != eHEAD); /* * If a 'go' (or 'gotofirst') parameter has been specified, attempt to goto that room * prior to doing anything else. */ if (havebstr("go")) { int ret; if (verbose) syslog(LOG_DEBUG, "Explicit room selection: %s", bstr("go")); ret = gotoroom(sbstr("go")); /* do quietly to avoid session output! */ if ((ret/100) != 2) { if (verbose) syslog(LOG_DEBUG, "Unable to change to [%s]; Reason: %d", bstr("go"), ret); } } else if (havebstr("gotofirst")) { int ret; if (verbose) syslog(LOG_DEBUG, "Explicit room selection: %s", bstr("gotofirst")); ret = gotoroom(sbstr("gotofirst")); /* do quietly to avoid session output! */ if ((ret/100) != 2) { syslog(LOG_INFO, "Unable to change to [%s]; Reason: %d", bstr("gotofirst"), ret); } } /* * If we aren't in any room yet, but we have cookie data telling us where we're * supposed to be, and 'go' was not specified, then go there. */ else if ( (StrLength(WCC->CurRoom.name) == 0) && ( (StrLength(WCC->Hdr->c_roomname) > 0) )) { int ret; if (verbose) syslog(LOG_DEBUG, "We are in '%s' but cookie indicates '%s', going there...", ChrPtr(WCC->CurRoom.name), ChrPtr(WCC->Hdr->c_roomname) ); ret = gotoroom(WCC->Hdr->c_roomname); /* do quietly to avoid session output! */ if ((ret/100) != 2) { if (verbose) syslog(LOG_DEBUG, "COOKIEGOTO: Unable to change to [%s]; Reason: %d", ChrPtr(WCC->Hdr->c_roomname), ret); } } if (WCC->Hdr->HR.Handler != NULL) { if ( (!WCC->logged_in) && ((WCC->Hdr->HR.Handler->Flags & ANONYMOUS) == 0) && (WCC->serv_info != NULL) && (WCC->serv_info->serv_supports_guest == 0) ) { display_login(); } else { if ((WCC->Hdr->HR.Handler->Flags & AJAX) != 0) { begin_ajax_response(); } WCC->Hdr->HR.Handler->F(); if ((WCC->Hdr->HR.Handler->Flags & AJAX) != 0) { end_ajax_response(); } } } /* When all else fails, display the default landing page or a main menu. */ else { /* * ordinary browser users get a nice login screen, DAV etc. requsets * are given a 401 so they can handle it appropriate. */ if (!WCC->logged_in) { if (xhttp) { authorization_required(); } else { display_default_landing_page(); } } /* * Toplevel dav requests? or just a flat browser request? */ else { if (xhttp) { dav_main(); } else { display_main_menu(); } } } SKIP_ALL_THIS_CRAP: FreeStrBuf(&Buf); fflush(stdout); }
BOOL DoCgiWork(int & argc, LPTSTR* &argv, Buf &lpszMessage, Buf & lpszCgiSuccessUrl, Buf &lpszCgiFailureUrl, Buf & lpszFirstReceivedData, Buf &lpszOtherHeader) { Buf lpszMethod; Buf lpszPost; Buf lpszParamCgi; Buf lpszQueryString; Buf lpszPathTranslated; Buf lpszCmdBlat; lpszMessage.Clear(); lpszFirstReceivedData.Clear(); lpszOtherHeader.Clear(); GetEnv(__T("REQUEST_METHOD"), lpszMethod); lpszPost=__T(""); if ( lstrcmpi(lpszMethod.Get(),__T("POST")) == 0) ReadPostData(lpszPost); GetEnv(__T("QUERY_STRING"), lpszQueryString); // lpszParamCgi.AllocExact(lpszQueryString.Length()+lpszPost.Length()+10); lpszParamCgi.Add( lpszQueryString ); if (lpszQueryString.Length() && lpszPost.Length()) lpszParamCgi.Add( __T('&') ); lpszParamCgi.Add( lpszPost ); GetEnv(__T("PATH_TRANSLATED"), lpszPathTranslated); BuildMessageAndCmdLine(lpszParamCgi,lpszPathTranslated.Get(),lpszCmdBlat,lpszMessage); SearchVar(lpszParamCgi, __T("BLAT_SUCCESS"), TRUE, lpszCgiSuccessUrl); SearchVar(lpszParamCgi, __T("BLAT_FAILURE"), TRUE, lpszCgiFailureUrl); // now replace %__% by var DWORD dwPos = 0; DWORD dwLineLen = (DWORD)lpszCmdBlat.Length(); while ( dwPos < dwLineLen ) { if ( *(lpszCmdBlat.Get()+dwPos) == __T('%') ) { Buf lpVarNameForSearch; Buf lpContentVar; DWORD dwEnd; dwEnd = (SearchNextPercent(lpszCmdBlat.Get()+dwPos+1)); if ( *(lpszCmdBlat.Get()+dwPos+1+dwEnd) == __T('\0') ) { lpContentVar.Free(); break; } lpVarNameForSearch.Alloc(dwEnd+0x10); lpVarNameForSearch.Clear(); memcpy(lpVarNameForSearch.Get(),lpszCmdBlat.Get()+dwPos+1,dwEnd*sizeof(_TCHAR)); lpVarNameForSearch.SetLength(dwEnd); *lpVarNameForSearch.GetTail() = __T('\0'); SearchVar(lpszParamCgi, lpVarNameForSearch.Get(), TRUE, lpContentVar); if ( lpContentVar.Length() ) { DWORD dwLenContentVar; dwLenContentVar = (DWORD)lpContentVar.Length(); lpszCmdBlat.Alloc(dwLineLen+dwLenContentVar+0x10); memmove(lpszCmdBlat.Get()+dwPos+dwLenContentVar,lpszCmdBlat.Get()+dwPos+dwEnd+2,(dwLineLen-(dwPos+dwEnd+1))*sizeof(_TCHAR)); memcpy(lpszCmdBlat.Get()+dwPos,lpContentVar.Get(),dwLenContentVar*sizeof(_TCHAR)); lpszCmdBlat.SetLength(); dwLineLen = (DWORD)lpszCmdBlat.Length(); dwPos += dwLenContentVar; } else dwPos += dwEnd + 1; lpVarNameForSearch.Free(); lpContentVar.Free(); } else dwPos++; } ReadCommandLine(lpszCmdBlat.Get(),argc,argv); lpszCmdBlat.Clear(); lpszParamCgi.Clear(); //LPTSTR lpszRemoteHost=GetEnv(__T("REMOTE_HOST")); Buf lpszRemoteAddr; GetEnv(__T("REMOTE_ADDR"), lpszRemoteAddr); Buf lpszServerName; GetEnv(__T("SERVER_NAME"), lpszServerName); Buf lpszHttpVia; GetEnv(__T("HTTP_VIA"), lpszHttpVia); Buf lpszHttpForwarded; GetEnv(__T("HTTP_FORWARDED"), lpszHttpForwarded); Buf lpszHttpForwardedFor; GetEnv(__T("HTTP_X_FORWARDED_FOR"), lpszHttpForwardedFor); Buf lpszHttpUserAgent; GetEnv(__T("HTTP_USER_AGENT"), lpszHttpUserAgent); Buf lpszHttpReferer; GetEnv(__T("HTTP_REFERER"), lpszHttpReferer); _TCHAR tmpBuf[0x2000]; if ( *lpszHttpUserAgent.Get() ) { _stprintf(tmpBuf, __T("X-Web-Browser: Send using %s\r\n"), lpszHttpUserAgent.Get()); lpszOtherHeader.Add(tmpBuf); } if ( *lpszHttpForwarded.Get() ) { _stprintf(tmpBuf, __T("X-Forwarded: %s\r\n"), lpszHttpForwarded.Get()); lpszOtherHeader.Add(tmpBuf); } if ( *lpszHttpForwardedFor.Get() ) { _stprintf(tmpBuf, __T("X-X-Forwarded-For: %s\r\n"), lpszHttpForwardedFor.Get()); lpszOtherHeader.Add(tmpBuf); } if ( *lpszHttpVia.Get() ) { _stprintf(tmpBuf, __T("X-Via: %s\r\n"), lpszHttpVia.Get()); lpszOtherHeader.Add(tmpBuf); } if ( *lpszHttpReferer.Get() ) { _stprintf(tmpBuf, __T("X-Referer: %s\r\n"), lpszHttpReferer.Get()); lpszOtherHeader.Add(tmpBuf); } _stprintf(tmpBuf, __T("Received: from %s by %s with HTTP; "), lpszRemoteAddr.Get(), lpszServerName.Get()); lpszFirstReceivedData.Add(tmpBuf); lpszRemoteAddr.Free(); lpszServerName.Free(); lpszHttpVia.Free(); lpszHttpForwarded.Free(); lpszHttpForwardedFor.Free(); lpszHttpUserAgent.Free(); lpszHttpReferer.Free(); lpszMethod.Free(); lpszPost.Free(); lpszParamCgi.Free(); lpszQueryString.Free(); lpszPathTranslated.Free(); lpszCmdBlat.Free(); return TRUE; }