2 * @file packet_editor.cpp
3 * @brief Packet Editor Header
5 * Copyright (C) 2009 NTT COMWARE Corporation.
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
22 **********************************************************************/
24 #include <boost/regex.hpp>
25 #include "packet_editor.h"
27 #include "sslproxyserver.h"
28 #include "sslproxysession.h"
31 * Packet editor constructor.
33 packet_editor::packet_editor(const sslproxy_session* session)
35 /*-------- DEBUG LOG --------*/
36 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
37 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 1,
38 "in_function : Constructor packet_editor::packet_editor(const sslproxysession* session)");
40 /*------ DEBUG LOG END ------*/
42 this->session = session;
44 /*-------- DEBUG LOG --------*/
45 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
46 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 2,
47 "out_function : Constructor packet_editor::packet_editor(const sslproxysession* session)");
49 /*------ DEBUG LOG END ------*/
53 * Packet editor destructor.
55 packet_editor::~packet_editor()
57 /*-------- DEBUG LOG --------*/
58 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
59 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 3,
60 "in/out_function : Destructor packet_editor::~packet_editor(void)");
62 /*------ DEBUG LOG END ------*/
66 * Edit client message function.
68 void packet_editor::edit_client(char* client_msg, size_t& client_length)
70 /*-------- DEBUG LOG --------*/
71 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
72 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 4,
73 "in_function : void packet_editor::edit_client(char* client_msg, size_t& client_length) : "
74 "client_msg(%s), client_length(%d)", client_msg, client_length);
76 /*------ DEBUG LOG END ------*/
78 // Edit HTTP (request header)
79 std::list<std::pair<std::string, std::string > >::iterator it, end;
80 it = ::http_request_header.begin();
81 end = ::http_request_header.end();
82 http_request request(std::string(client_msg, client_length));
83 for (;it != end; ++it) {
84 // Set request header field
85 if (it->first == "set") {
86 // "Header-Field-Name":"Set-Value"
87 std::vector<std::string> set_vector = split(it->second, ":", 2);
88 if (set_vector.size() == 2)
89 expand_macro(set_vector.at(1));
90 // Overwrite or insert.
91 request.header(set_vector.at(0), set_vector.at(1));
93 // Remove request header field
94 else if (it->first == "unset") {
95 // "Header-Field-Name"
96 request.header(it->second, "");
98 // Add request header field
99 else if (it->first == "add") {
100 // "Header-Field-Name":"Set-Value"
101 std::vector<std::string> add_vector = split(it->second, ":", 2);
102 if (add_vector.size() == 2) {
103 field_range current_range = request.header(add_vector.at(0));
104 expand_macro(add_vector.at(1));
105 // If header field already exists, concatinate values.
106 if (current_range.first != current_range.second) {
107 std::string new_value = current_range.first->second;
108 new_value += "," + add_vector.at(1);
109 request.header(add_vector.at(0), new_value);
110 // otherwise insert new header field.
112 request.header(add_vector.at(0), add_vector.at(1));
116 // Replace request header field using regular expression
117 else if (it->first == "replace") {
118 // "Header-Field-Name":"From-Value(regex)":"To-Value"
119 std::vector<std::string> replace_vector = split(it->second, ":", 3);
120 if (replace_vector.size() == 3) {
121 field_range current_range = request.header(replace_vector.at(0));
122 expand_macro(replace_vector.at(1));
123 expand_macro(replace_vector.at(2));
124 boost::regex exp(replace_vector.at(1));
125 for (;current_range.first != current_range.second; current_range.first++) {
126 std::string new_value = current_range.first->second;
127 // Replace only if exist
128 if (boost::regex_search(new_value, exp)) {
129 new_value = boost::regex_replace(new_value, exp, replace_vector.at(2));
130 request.header(replace_vector.at(0), new_value);
138 * Insert other protocol editor.
141 std::string edited = request.as_string();
142 // New client message is too long (over buffer size)
143 if (edited.size() > MAX_BUFFER_SIZE) {
144 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT, 1, "Edited message is too long. Drop message.");
147 // Set new client message size.
148 client_length = edited.size();
149 // Set new client message.
150 memcpy(client_msg, edited.c_str(), client_length);
153 /*-------- DEBUG LOG --------*/
154 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
155 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 5,
156 "out_function : void packet_editor::edit_client(char* client_msg, size_t& client_length)");
158 /*------ DEBUG LOG END ------*/
162 * Edit server message function.
164 void packet_editor::edit_server(char* server_msg, size_t& server_length)
166 /*-------- DEBUG LOG --------*/
167 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
168 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 6,
169 "in_function : void packet_editor::edit_server(char* server_msg, size_t& server_length) : "
170 "server_msg(%s), server_length(%d)", server_msg, server_length);
172 /*------ DEBUG LOG END ------*/
174 // Edit HTTP (response header)
175 std::list<std::pair<std::string, std::string > >::iterator it, end;
176 it = ::http_response_header.begin();
177 end = ::http_response_header.end();
178 http_response response(std::string(server_msg, server_length));
179 for (;it != end; ++it) {
180 // Set request header field
181 if (it->first == "set") {
182 // "Header-Field-Name":"Set-Value"
183 std::vector<std::string> set_vector = split(it->second, ":", 2);
184 if (set_vector.size() == 2)
185 expand_macro(set_vector.at(1));
186 // Overwrite or insert.
187 response.header(set_vector.at(0), set_vector.at(1));
189 // Remove request header field
190 else if (it->first == "unset") {
191 // "Header-Field-Name"
192 response.header(it->second, "");
194 // Add request header field
195 else if (it->first == "add") {
196 // "Header-Field-Name":"Set-Value"
197 std::vector<std::string> add_vector = split(it->second, ":", 2);
198 if (add_vector.size() == 2) {
199 field_range current_range = response.header(add_vector.at(0));
200 expand_macro(add_vector.at(1));
201 // If header field already exists, concatinate values.
202 if (current_range.first != current_range.second) {
203 std::string new_value = current_range.first->second;
204 new_value += "," + add_vector.at(1);
205 response.header(add_vector.at(0), new_value);
206 // otherwise insert new header field.
208 response.header(add_vector.at(0), add_vector.at(1));
212 // Replace request header field using regular expression
213 else if (it->first == "replace") {
214 // "Header-Field-Name":"From-Value(regex)":"To-Value"
215 std::vector<std::string> replace_vector = split(it->second, ":", 3);
216 if (replace_vector.size() == 3) {
217 field_range current_range = response.header(replace_vector.at(0));
218 expand_macro(replace_vector.at(1));
219 expand_macro(replace_vector.at(2));
220 boost::regex exp(replace_vector.at(1));
221 for (;current_range.first != current_range.second; current_range.first++) {
222 std::string new_value = current_range.first->second;
223 // Replace only if exist
224 if (boost::regex_search(new_value, exp)) {
225 new_value = boost::regex_replace(new_value, exp, replace_vector.at(2));
226 response.header(replace_vector.at(0), new_value);
234 * Insert other protocol editor.
237 std::string edited = response.as_string();
238 // New server message is too long (over buffer size)
239 if (edited.size() > MAX_BUFFER_SIZE) {
240 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT, 2, "Edited message is too long. Drop message.");
243 // Set new server message size.
244 server_length = edited.size();
245 // Set new server message.
246 memcpy(server_msg, edited.c_str(), server_length);
249 /*-------- DEBUG LOG --------*/
250 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
251 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 7,
252 "out_function : void packet_editor::edit_server(char* server_msg, size_t& server_length)");
254 /*------ DEBUG LOG END ------*/
258 * Expand macro function.
260 * @param[in/out] source string
262 void packet_editor::expand_macro(std::string& source) {
263 /*-------- DEBUG LOG --------*/
264 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
265 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 8,
266 "in_function : void packet_editor::expand_macro(std::string& source) : "
267 "source(%s)", source.c_str());
269 /*------ DEBUG LOG END ------*/
272 pos = source.find("%{CLIENT_ADDR}");
273 if (pos != std::string::npos) {
274 std::string endpoint = this->session->get_remote_endpoint();
275 if (endpoint.length() > 0) {
276 int addr_end = endpoint.find(':');
277 source.replace(pos, 14, endpoint.substr(0, addr_end));
281 pos = source.find("%{CLIENT_PORT}");
282 if (pos != std::string::npos) {
283 std::string endpoint = this->session->get_remote_endpoint();
284 if (endpoint.length() > 0) {
285 int port_begin = endpoint.find(':') + 1;
286 source.replace(pos, 14, endpoint.substr(port_begin, endpoint.length() - port_begin));
290 pos = source.find("%{SERVER_ADDR}");
291 if (pos != std::string::npos) {
292 int addr_end = ::target_endpoint.find(':');
293 source.replace(pos, 14, ::target_endpoint.substr(0, addr_end));
296 pos = source.find("%{SERVER_PORT}");
297 if (pos != std::string::npos) {
298 int port_begin = ::target_endpoint.find(':') + 1;
299 source.replace(pos, 14, ::target_endpoint.substr(port_begin, ::target_endpoint.length() - port_begin));
302 pos = source.find("%{RECV_ADDR}");
303 if (pos != std::string::npos) {
304 int addr_end = ::recv_endpoint.find(':');
305 source.replace(pos, 12, ::recv_endpoint.substr(0, addr_end));
308 pos = source.find("%{RECV_PORT}");
309 if (pos != std::string::npos) {
310 int port_begin = ::recv_endpoint.find(':') + 1;
311 source.replace(pos, 12, ::recv_endpoint.substr(port_begin, ::recv_endpoint.length() - port_begin));
314 /*-------- DEBUG LOG --------*/
315 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
316 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 9,
317 "out_function : void packet_editor::expand_macro(std::string& source)");
319 /*------ DEBUG LOG END ------*/
323 * Split string function.
324 * Split string by delimiter and return token vector.
325 * If limit is specified and positive, it represents the maximum number of fields
326 * the delimiter will be split into.
328 * @param[in] source string
329 * @param[in] delimiter delimiter
330 * @param[in] limit max token
332 std::vector<std::string> packet_editor::split(const std::string& source, const std::string& delimiter, int limit = 0) {
333 /*-------- DEBUG LOG --------*/
334 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
335 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 10,
336 "in_function : std::vector<std::string> packet_editor::split"
337 "(const std::string& source, const std::string& delimiter, int limit) : "
338 "source(%s), delimiter(%s), limit(%d)", source.c_str(), delimiter.c_str(), limit);
340 /*------ DEBUG LOG END ------*/
341 std::vector<std::string> words;
343 int end = source.size();
346 end = source.find(delimiter, begin);
347 if (end == std::string::npos) {
351 words.push_back(source.substr(begin, end - begin));
355 words.push_back(source.substr(begin, end - begin));
356 /*-------- DEBUG LOG --------*/
357 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
358 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 11,
359 "out_function : std::vector<std::string> packet_editor::split"
360 "(const std::string& source, const std::string& delimiter, int limit)");
362 /*------ DEBUG LOG END ------*/