Exemple #1
0
////////////////////////////////////////////////////////////////////////////////////////////
/// 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;
}
Exemple #2
0
/*
 * 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);
}
Exemple #3
0
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;
}