Skip to content

Commit 165b392

Browse files
committed
Merge branch 'WD_1.X_dev' of https://portal-ua.globallogic.com/git/wd into WD_1.X_dev
2 parents ce19f39 + 887e731 commit 165b392

File tree

8 files changed

+250
-2
lines changed

8 files changed

+250
-2
lines changed

inc/webdriver_access.h

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#ifndef WEBDRIVER_ACCESS_H
2+
#define WEBDRIVER_ACCESS_H
3+
4+
#include <string>
5+
#include <vector>
6+
#include <list>
7+
#include "base/file_util.h"
8+
9+
namespace webdriver {
10+
11+
struct AccessCommandTable
12+
{
13+
std::string method;
14+
std::string url;
15+
};
16+
17+
struct AccessRule {
18+
long hostIp;
19+
bool isGeneralRule; //for all ip
20+
bool allowed;
21+
std::vector<AccessCommandTable> commandList;
22+
};
23+
24+
class AccessValidator
25+
{
26+
public:
27+
AccessValidator();
28+
~AccessValidator();
29+
void setWhiteList(FilePath &xmlPath);
30+
bool isAllowed(const long &remote_ip, const std::string &url, const std::string &method);
31+
32+
private:
33+
bool convertIpString(const char *str_ip, long *int_ip);
34+
std::list<AccessRule> accessList;
35+
};
36+
37+
} // namespace webdriver
38+
39+
#endif // WEBDRIVER_ACCESS_H

inc/webdriver_server.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ For all options please refer:
6161
#include "base/command_line.h"
6262
#include "base/memory/singleton.h"
6363
#include "base/values.h"
64+
#include "webdriver_access.h"
6465

6566
struct mg_context;
6667
struct mg_connection;
@@ -127,6 +128,7 @@ class Server {
127128
std::string url_base_;
128129
struct mg_context* mg_ctx_;
129130
State state_;
131+
AccessValidator accessValidor;
130132

131133
void DispatchCommand(const std::string& matched_route,
132134
Command* command_ptr,

inc/webdriver_switches.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,13 @@ class Switches {
7979
/// if parameter specified, user input device enabled
8080
static const char kUserInputDevice[];
8181

82+
/// \page page_webdriver_switches WD Server switches
83+
/// - <b>config</b><br>
84+
/// The path to whitelist file (e.g. whitelist.xml) in
85+
/// XML format with specified list of IP with allowed/disallowed
86+
/// commands for each of them
87+
static const char kWhiteList[];
88+
8289
};
8390

8491
} // namespace webdriver

src/webdriver/webdriver_access.cc

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
#include "webdriver_access.h"
2+
#include "webdriver_logging.h"
3+
#include <base/string_util.h>
4+
#include "third_party/pugixml/pugixml.hpp"
5+
6+
namespace webdriver {
7+
8+
AccessValidator::AccessValidator(){
9+
}
10+
11+
AccessValidator::~AccessValidator(){
12+
}
13+
14+
bool AccessValidator::isAllowed(const long &remote_ip, const std::string &url, const std::string &method)
15+
{
16+
if (accessList.empty())
17+
return true;
18+
bool result = false;
19+
for (std::list<AccessRule>::iterator it = accessList.begin(); it != accessList.end(); ++it)
20+
{
21+
AccessRule host = *it;
22+
if ((host.hostIp == remote_ip) || (host.isGeneralRule))
23+
{
24+
if (!host.allowed) {
25+
for (std::vector<AccessCommandTable>::iterator it = host.commandList.begin(); it != host.commandList.end(); ++it) {
26+
AccessCommandTable table = *it;
27+
if (MatchPattern(url, table.url) && MatchPattern(method, table.method))
28+
return false;
29+
}
30+
return true;
31+
} else {
32+
if (host.commandList.empty())
33+
return true;
34+
for (std::vector<AccessCommandTable>::iterator it = host.commandList.begin(); it != host.commandList.end(); ++it) {
35+
AccessCommandTable table = *it;
36+
if (MatchPattern(url, table.url) && MatchPattern(method, table.method))
37+
return true;
38+
}
39+
return false;
40+
}
41+
}
42+
}
43+
return result;
44+
}
45+
46+
void AccessValidator::setWhiteList(FilePath &xmlPath)
47+
{
48+
std::string white_list;
49+
50+
if (file_util::ReadFileToString(xmlPath, &white_list))
51+
{
52+
const void* content = white_list.c_str();
53+
int content_size = white_list.size();
54+
55+
pugi::xml_document doc;
56+
pugi::xml_parse_result result = doc.load_buffer(content, content_size);
57+
58+
if (result) {
59+
// Select host nodes
60+
pugi::xpath_query query_nodes("/hosts/host");
61+
pugi::xpath_node_set found_nodes = query_nodes.evaluate_node_set(doc);
62+
63+
if ( (NULL == query_nodes.result().error) &&
64+
(pugi::xpath_type_node_set == query_nodes.return_type()) ) {
65+
for (pugi::xpath_node_set::const_iterator it = found_nodes.begin(); it != found_nodes.end(); ++it) {
66+
pugi::xpath_node node = *it;
67+
pugi::xml_node xnode = node.node();
68+
pugi::xml_attribute atr = xnode.attribute("ip");
69+
70+
AccessRule rule;
71+
rule.isGeneralRule = false;
72+
rule.allowed = true;
73+
74+
if (!convertIpString(atr.value(), &rule.hostIp)) {
75+
if (!strcmp(atr.value(), "*")) {
76+
rule.isGeneralRule = true;
77+
} else {
78+
std::string error_descr = "WhiteList: "+ std::string(atr.value()) + " is not a valid ip address";
79+
GlobalLogger::Log(kWarningLogLevel, error_descr);
80+
continue;
81+
}
82+
83+
}
84+
85+
pugi::xpath_query query_nodes("./deny");
86+
pugi::xpath_node_set deny_nodes = query_nodes.evaluate_node_set(xnode);
87+
if ( (NULL == query_nodes.result().error) &&
88+
(pugi::xpath_type_node_set == query_nodes.return_type()) ) {
89+
for (pugi::xpath_node_set::const_iterator it = deny_nodes.begin(); it != deny_nodes.end(); ++it) {
90+
pugi::xpath_node node = *it;
91+
pugi::xml_node xnode = node.node();
92+
pugi::xml_attribute atr = xnode.attribute("url");
93+
94+
AccessCommandTable rt;
95+
rt.url = atr.value();
96+
atr = xnode.attribute("method");
97+
rt.method = atr.value();
98+
rule.commandList.push_back(rt);
99+
rule.allowed = false;
100+
}
101+
}
102+
if (rule.allowed)
103+
{
104+
pugi::xpath_query query_nodes("./allow");
105+
pugi::xpath_node_set allow_nodes = query_nodes.evaluate_node_set(xnode);
106+
if ( (NULL == query_nodes.result().error) &&
107+
(pugi::xpath_type_node_set == query_nodes.return_type()) ) {
108+
for (pugi::xpath_node_set::const_iterator it = allow_nodes.begin(); it != allow_nodes.end(); ++it) {
109+
pugi::xpath_node node = *it;
110+
pugi::xml_node xnode = node.node();
111+
pugi::xml_attribute atr = xnode.attribute("url");
112+
AccessCommandTable rt;
113+
rt.url = atr.value();
114+
atr = xnode.attribute("method");
115+
rt.method = atr.value();
116+
rule.commandList.push_back(rt);
117+
}
118+
}
119+
}
120+
// if we have wildcard put this rule in the end
121+
rule.isGeneralRule ? accessList.push_back(rule) : accessList.push_front(rule);
122+
}
123+
} else {
124+
std::string error_descr = "WhiteList: Cant evaluate XPath to node set: ";
125+
error_descr += query_nodes.result().description();
126+
GlobalLogger::Log(kWarningLogLevel, error_descr);
127+
}
128+
}
129+
else
130+
{
131+
std::string error_descr = " Error description: ";
132+
error_descr += result.description();
133+
GlobalLogger::Log(kWarningLogLevel, "WhiteList: XML parsed with errors:");
134+
GlobalLogger::Log(kWarningLogLevel, error_descr);
135+
}
136+
137+
// destroy tree
138+
doc.reset();
139+
}
140+
else
141+
{
142+
GlobalLogger::Log(kWarningLogLevel, "WhiteList: Can't read file");
143+
}
144+
}
145+
146+
bool AccessValidator::convertIpString(const char *str_ip, long *int_ip)
147+
{
148+
bool result = false;
149+
char *p, c;
150+
long octet, n;
151+
152+
*int_ip = 0;
153+
octet = 0;
154+
n = 0;
155+
156+
char buff[sizeof "000.000.000.000"];
157+
if (strlen(str_ip) < sizeof buff) {
158+
strcpy(buff, str_ip);
159+
}
160+
161+
for (p = buff; *p != '\0' ; ++p) {
162+
c = *p;
163+
if (c >= '0' && c <= '9') {
164+
octet = octet * 10 + (c - '0');
165+
continue;
166+
}
167+
if (c == '.' && octet < 256) {
168+
*int_ip = (*int_ip << 8) + octet;
169+
octet = 0;
170+
n++;
171+
continue;
172+
}
173+
return result;
174+
}
175+
176+
if (n == 3 && octet < 256) {
177+
*int_ip = (*int_ip << 8) + octet;
178+
result = true;
179+
}
180+
return result;
181+
}
182+
183+
} // namespace webdriver

src/webdriver/webdriver_server.cc

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
#include "webdriver_view_enumerator.h"
3434
#include "webdriver_view_executor.h"
3535

36-
3736
namespace webdriver {
3837

3938
Server::Server()
@@ -80,6 +79,13 @@ int Server::Configure(const CommandLine &options) {
8079
"\nBuild Time: "+ VersionInfo::BuildDateTime() ;
8180
GlobalLogger::Log(kInfoLogLevel, driver_info);
8281

82+
if (options.HasSwitch(webdriver::Switches::kWhiteList))
83+
{
84+
FilePath xmlPath(options_->GetSwitchValueNative(webdriver::Switches::kWhiteList));
85+
accessValidor.setWhiteList(xmlPath);
86+
}
87+
88+
8389
// set default route table
8490
routeTable_.reset(new DefaultRouteTable());
8591

@@ -426,6 +432,14 @@ bool Server::ParseRequestInfo(const struct mg_request_info* const request_info,
426432

427433
base::SplitString(uri, '/', path_segments);
428434

435+
if (!accessValidor.isAllowed(request_info->remote_ip, uri, *method))
436+
{
437+
response->SetError(new Error(
438+
kUnknownError,
439+
"Command is forbidden for this origin"));
440+
return false;
441+
}
442+
429443
if (*method == "POST") {
430444
std::string json;
431445
ReadRequestBody(request_info, connection, &json);

src/webdriver/webdriver_switches.cc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,4 +26,6 @@ const char Switches::kVNCLogin[] = "vnc-login";
2626

2727
const char Switches::kUserInputDevice[] = "uinput";
2828

29+
const char Switches::kWhiteList[] = "white-list";
30+
2931
} // namespace webdriver

wd_core.gyp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@
5858
'src/webdriver/frame_path.cc',
5959
'src/webdriver/http_response.cc',
6060
'src/webdriver/value_conversion_traits.cc',
61+
'src/webdriver/webdriver_access.cc',
6162
'src/webdriver/webdriver_basic_types.cc',
6263
'src/webdriver/webdriver_capabilities_parser.cc',
6364
'src/webdriver/webdriver_element_id.cc',
@@ -78,6 +79,7 @@
7879
'src/webdriver/url_command_wrapper.cc',
7980
'src/webdriver/versioninfo.cc',
8081
'src/webdriver/webdriver_version.cc',
82+
'src/third_party/pugixml/pugixml.cpp'
8183
],
8284

8385
'conditions': [

wd_ext_qt.gyp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@
5555
'src/webdriver/extension_qt/vnc_event_dispatcher.cc',
5656
'src/webdriver/extension_qt/wd_event_dispatcher.cc',
5757
'src/webdriver/extension_qt/uinput_event_dispatcher.cc',
58-
'src/third_party/pugixml/pugixml.cpp'
5958
],
6059

6160
'conditions': [

0 commit comments

Comments
 (0)