mirror of
https://github.com/deneraraujo/OpenVPNAdapter.git
synced 2026-04-24 00:00:05 +08:00
Merge commit '86cc97e55fe346502462284d2e636a2b3708163e' as 'Sources/OpenVPN3'
This commit is contained in:
@@ -0,0 +1,283 @@
|
||||
// OpenVPN -- An application to securely tunnel IP networks
|
||||
// over a single port, with support for SSL/TLS-based
|
||||
// session authentication and key exchange,
|
||||
// packet encryption, packet authentication, and
|
||||
// packet compression.
|
||||
//
|
||||
// Copyright (C) 2012-2017 OpenVPN Inc.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License Version 3
|
||||
// as published by the Free Software Foundation.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program in the COPYING file.
|
||||
// If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
// A state machine to skip extraneous HTML in an
|
||||
// HTTP CONNECT proxy response.
|
||||
|
||||
// Matches on typical HTML blocks:
|
||||
//
|
||||
// <!doctype html> ... </html>
|
||||
// <html> ... </html>
|
||||
//
|
||||
// Notes:
|
||||
// 1. Case insensitive
|
||||
// 2. </html> can be followed by CR/LF chars
|
||||
|
||||
#ifndef OPENVPN_HTTP_HTMLSKIP_H
|
||||
#define OPENVPN_HTTP_HTMLSKIP_H
|
||||
|
||||
#include <openvpn/buffer/buffer.hpp>
|
||||
|
||||
namespace openvpn {
|
||||
namespace HTTP {
|
||||
|
||||
class HTMLSkip
|
||||
{
|
||||
public:
|
||||
enum Status {
|
||||
PENDING,
|
||||
MATCH,
|
||||
NOMATCH,
|
||||
};
|
||||
|
||||
HTMLSkip()
|
||||
: state(INITIAL),
|
||||
residual(64, 0),
|
||||
bytes(0)
|
||||
{}
|
||||
|
||||
Status add(unsigned char c)
|
||||
{
|
||||
bool retain = false;
|
||||
|
||||
++bytes;
|
||||
switch (state)
|
||||
{
|
||||
case INITIAL:
|
||||
retain = true;
|
||||
if (c == '<')
|
||||
state = O_OPEN;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_OPEN:
|
||||
retain = true;
|
||||
if (c == '!')
|
||||
state = O_BANG;
|
||||
else if (c == 'h' || c == 'H')
|
||||
state = O_HTML_H;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_BANG:
|
||||
retain = true;
|
||||
if (c == 'd' || c == 'D')
|
||||
state = O_DOCTYPE_D;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_D:
|
||||
retain = true;
|
||||
if (c == 'o' || c == 'O')
|
||||
state = O_DOCTYPE_O;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_O:
|
||||
retain = true;
|
||||
if (c == 'c' || c == 'C')
|
||||
state = O_DOCTYPE_C;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_C:
|
||||
retain = true;
|
||||
if (c == 't' || c == 'T')
|
||||
state = O_DOCTYPE_T;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_T:
|
||||
retain = true;
|
||||
if (c == 'y' || c == 'Y')
|
||||
state = O_DOCTYPE_Y;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_Y:
|
||||
retain = true;
|
||||
if (c == 'p' || c == 'P')
|
||||
state = O_DOCTYPE_P;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_P:
|
||||
retain = true;
|
||||
if (c == 'e' || c == 'E')
|
||||
state = O_DOCTYPE_SPACE;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_DOCTYPE_SPACE:
|
||||
retain = true;
|
||||
if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
|
||||
break;
|
||||
else if (c == 'h' || c == 'H')
|
||||
state = O_HTML_H;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_HTML_H:
|
||||
retain = true;
|
||||
if (c == 't' || c == 'T')
|
||||
state = O_HTML_T;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_HTML_T:
|
||||
retain = true;
|
||||
if (c == 'm' || c == 'M')
|
||||
state = O_HTML_M;
|
||||
else
|
||||
state = FAIL;
|
||||
break;
|
||||
case O_HTML_M:
|
||||
if (c == 'l' || c == 'L')
|
||||
{
|
||||
state = CONTENT;
|
||||
residual.reset_content();
|
||||
}
|
||||
else
|
||||
{
|
||||
state = FAIL;
|
||||
retain = true;
|
||||
}
|
||||
break;
|
||||
case CONTENT:
|
||||
if (c == '<')
|
||||
state = C_OPEN;
|
||||
break;
|
||||
case C_OPEN:
|
||||
if (c == '/')
|
||||
state = C_SLASH;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_SLASH:
|
||||
if (c == 'h' || c == 'H')
|
||||
state = C_HTML_H;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_HTML_H:
|
||||
if (c == 't' || c == 'T')
|
||||
state = C_HTML_T;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_HTML_T:
|
||||
if (c == 'm' || c == 'M')
|
||||
state = C_HTML_M;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_HTML_M:
|
||||
if (c == 'l' || c == 'L')
|
||||
state = C_HTML_L;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_HTML_L:
|
||||
if (c == '>')
|
||||
state = C_CRLF;
|
||||
else
|
||||
state = CONTENT;
|
||||
break;
|
||||
case C_CRLF:
|
||||
if (!(c == '\n' || c == '\r'))
|
||||
{
|
||||
residual.reset_content();
|
||||
residual.push_back(c);
|
||||
state = DONE;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
retain = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (retain)
|
||||
residual.push_back(c);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case DONE:
|
||||
return MATCH;
|
||||
case FAIL:
|
||||
return NOMATCH;
|
||||
default:
|
||||
return PENDING;
|
||||
}
|
||||
}
|
||||
|
||||
void get_residual(BufferAllocated& buf) const
|
||||
{
|
||||
if (residual.size() <= buf.offset())
|
||||
{
|
||||
buf.prepend(residual.c_data(), residual.size());
|
||||
}
|
||||
else
|
||||
{
|
||||
BufferAllocated newbuf(residual.size() + buf.size(), 0);
|
||||
newbuf.write(residual.c_data(), residual.size());
|
||||
newbuf.write(buf.c_data(), buf.size());
|
||||
buf.move(newbuf);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long n_bytes() const { return bytes; }
|
||||
|
||||
private:
|
||||
enum State {
|
||||
DONE,
|
||||
FAIL,
|
||||
INITIAL,
|
||||
O_OPEN,
|
||||
O_BANG,
|
||||
O_DOCTYPE_D,
|
||||
O_DOCTYPE_O,
|
||||
O_DOCTYPE_C,
|
||||
O_DOCTYPE_T,
|
||||
O_DOCTYPE_Y,
|
||||
O_DOCTYPE_P,
|
||||
O_DOCTYPE_SPACE,
|
||||
O_HTML_H,
|
||||
O_HTML_T,
|
||||
O_HTML_M,
|
||||
CONTENT,
|
||||
C_OPEN,
|
||||
C_SLASH,
|
||||
C_HTML_H,
|
||||
C_HTML_T,
|
||||
C_HTML_M,
|
||||
C_HTML_L,
|
||||
C_CRLF,
|
||||
};
|
||||
|
||||
State state;
|
||||
BufferAllocated residual;
|
||||
unsigned long bytes;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user