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));
84 // Ignore when client_msg is not HTTP message
85 if (request.method().empty())
88 for (;it != end; ++it) {
89 // Set request header field
90 if (it->first == "set") {
91 // "Header-Field-Name":"Set-Value"
92 std::vector<std::string> set_vector = split(it->second, ":", 2);
93 if (set_vector.size() == 2)
94 expand_macro(set_vector.at(1));
95 // Overwrite or insert.
96 request.header(set_vector.at(0), set_vector.at(1));
98 // Remove request header field
99 else if (it->first == "unset") {
100 // "Header-Field-Name"
101 request.header(it->second, "");
103 // Add request header field
104 else if (it->first == "add") {
105 // "Header-Field-Name":"Set-Value"
106 std::vector<std::string> add_vector = split(it->second, ":", 2);
107 if (add_vector.size() == 2) {
108 field_range current_range = request.header(add_vector.at(0));
109 expand_macro(add_vector.at(1));
110 // If header field already exists, concatinate values.
111 if (current_range.first != current_range.second) {
112 std::string new_value = current_range.first->second;
113 new_value += "," + add_vector.at(1);
114 request.header(add_vector.at(0), new_value);
115 // otherwise insert new header field.
117 request.header(add_vector.at(0), add_vector.at(1));
121 // Replace request header field using regular expression
122 else if (it->first == "replace") {
123 // "Header-Field-Name":"From-Value(regex)":"To-Value"
124 std::vector<std::string> replace_vector = split(it->second, ":", 3);
125 if (replace_vector.size() == 3) {
126 field_range current_range = request.header(replace_vector.at(0));
127 expand_macro(replace_vector.at(1));
128 expand_macro(replace_vector.at(2));
129 boost::regex exp(replace_vector.at(1));
130 for (;current_range.first != current_range.second; current_range.first++) {
131 std::string new_value = current_range.first->second;
132 // Replace only if exist
133 if (boost::regex_search(new_value, exp)) {
134 new_value = boost::regex_replace(new_value, exp, replace_vector.at(2));
135 request.header(replace_vector.at(0), new_value);
143 * Insert other protocol editor.
148 if (request.modified()) {
149 std::string edited = request.as_string();
150 // New client message is too long (over buffer size)
151 if (edited.size() > MAX_BUFFER_SIZE) {
152 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT, 1, "Edited message is too long. Drop message.");
155 // Set new client message size.
156 client_length = edited.size();
157 // Set new client message.
158 memcpy(client_msg, edited.c_str(), client_length);
162 /*-------- DEBUG LOG --------*/
163 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
164 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 5,
165 "out_function : void packet_editor::edit_client(char* client_msg, size_t& client_length)");
167 /*------ DEBUG LOG END ------*/
171 * Edit server message function.
173 void packet_editor::edit_server(char* server_msg, size_t& server_length)
175 /*-------- DEBUG LOG --------*/
176 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
177 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 6,
178 "in_function : void packet_editor::edit_server(char* server_msg, size_t& server_length) : "
179 "server_msg(%s), server_length(%d)", server_msg, server_length);
181 /*------ DEBUG LOG END ------*/
183 // Edit HTTP (response header)
184 std::list<std::pair<std::string, std::string > >::iterator it, end;
185 it = ::http_response_header.begin();
186 end = ::http_response_header.end();
187 http_response response(std::string(server_msg, server_length));
189 // Ignore when server_msg is not HTTP message
190 if (response.http_version().empty())
191 goto packet_edit_out;
193 for (;it != end; ++it) {
194 // Set request header field
195 if (it->first == "set") {
196 // "Header-Field-Name":"Set-Value"
197 std::vector<std::string> set_vector = split(it->second, ":", 2);
198 if (set_vector.size() == 2)
199 expand_macro(set_vector.at(1));
200 // Overwrite or insert.
201 response.header(set_vector.at(0), set_vector.at(1));
203 // Remove request header field
204 else if (it->first == "unset") {
205 // "Header-Field-Name"
206 response.header(it->second, "");
208 // Add request header field
209 else if (it->first == "add") {
210 // "Header-Field-Name":"Set-Value"
211 std::vector<std::string> add_vector = split(it->second, ":", 2);
212 if (add_vector.size() == 2) {
213 field_range current_range = response.header(add_vector.at(0));
214 expand_macro(add_vector.at(1));
215 // If header field already exists, concatinate values.
216 if (current_range.first != current_range.second) {
217 std::string new_value = current_range.first->second;
218 new_value += "," + add_vector.at(1);
219 response.header(add_vector.at(0), new_value);
220 // otherwise insert new header field.
222 response.header(add_vector.at(0), add_vector.at(1));
226 // Replace request header field using regular expression
227 else if (it->first == "replace") {
228 // "Header-Field-Name":"From-Value(regex)":"To-Value"
229 std::vector<std::string> replace_vector = split(it->second, ":", 3);
230 if (replace_vector.size() == 3) {
231 field_range current_range = response.header(replace_vector.at(0));
232 expand_macro(replace_vector.at(1));
233 expand_macro(replace_vector.at(2));
234 boost::regex exp(replace_vector.at(1));
235 for (;current_range.first != current_range.second; current_range.first++) {
236 std::string new_value = current_range.first->second;
237 // Replace only if exist
238 if (boost::regex_search(new_value, exp)) {
239 new_value = boost::regex_replace(new_value, exp, replace_vector.at(2));
240 response.header(replace_vector.at(0), new_value);
248 * Insert other protocol editor.
253 if (response.modified()) {
254 std::string edited = response.as_string();
255 // New server message is too long (over buffer size)
256 if (edited.size() > MAX_BUFFER_SIZE) {
257 LOGGER_PUT_LOG_ERROR(LOG_CAT_PACKET_EDIT, 2, "Edited message is too long. Drop message.");
260 // Set new server message size.
261 server_length = edited.size();
262 // Set new server message.
263 memcpy(server_msg, edited.c_str(), server_length);
267 /*-------- DEBUG LOG --------*/
268 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
269 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 7,
270 "out_function : void packet_editor::edit_server(char* server_msg, size_t& server_length)");
272 /*------ DEBUG LOG END ------*/
276 * Expand macro function.
278 * @param[in/out] source string
280 void packet_editor::expand_macro(std::string& source) {
281 /*-------- DEBUG LOG --------*/
282 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
283 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 8,
284 "in_function : void packet_editor::expand_macro(std::string& source) : "
285 "source(%s)", source.c_str());
287 /*------ DEBUG LOG END ------*/
290 pos = source.find("%{CLIENT_ADDR}");
291 if (pos != std::string::npos) {
292 std::string endpoint = this->session->get_remote_endpoint();
293 if (endpoint.length() > 0) {
294 int addr_end = endpoint.find(':');
295 source.replace(pos, 14, endpoint.substr(0, addr_end));
299 pos = source.find("%{CLIENT_PORT}");
300 if (pos != std::string::npos) {
301 std::string endpoint = this->session->get_remote_endpoint();
302 if (endpoint.length() > 0) {
303 int port_begin = endpoint.find(':') + 1;
304 source.replace(pos, 14, endpoint.substr(port_begin, endpoint.length() - port_begin));
308 pos = source.find("%{SERVER_ADDR}");
309 if (pos != std::string::npos) {
310 int addr_end = ::target_endpoint.find(':');
311 source.replace(pos, 14, ::target_endpoint.substr(0, addr_end));
314 pos = source.find("%{SERVER_PORT}");
315 if (pos != std::string::npos) {
316 int port_begin = ::target_endpoint.find(':') + 1;
317 source.replace(pos, 14, ::target_endpoint.substr(port_begin, ::target_endpoint.length() - port_begin));
320 pos = source.find("%{RECV_ADDR}");
321 if (pos != std::string::npos) {
322 int addr_end = ::recv_endpoint.find(':');
323 source.replace(pos, 12, ::recv_endpoint.substr(0, addr_end));
326 pos = source.find("%{RECV_PORT}");
327 if (pos != std::string::npos) {
328 int port_begin = ::recv_endpoint.find(':') + 1;
329 source.replace(pos, 12, ::recv_endpoint.substr(port_begin, ::recv_endpoint.length() - port_begin));
332 /*-------- DEBUG LOG --------*/
333 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
334 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 9,
335 "out_function : void packet_editor::expand_macro(std::string& source)");
337 /*------ DEBUG LOG END ------*/
341 * Split string function.
342 * Split string by delimiter and return token vector.
343 * If limit is specified and positive, it represents the maximum number of fields
344 * the delimiter will be split into.
346 * @param[in] source string
347 * @param[in] delimiter delimiter
348 * @param[in] limit max token
350 std::vector<std::string> packet_editor::split(const std::string& source, const std::string& delimiter, int limit = 0) {
351 /*-------- DEBUG LOG --------*/
352 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
353 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 10,
354 "in_function : std::vector<std::string> packet_editor::split"
355 "(const std::string& source, const std::string& delimiter, int limit) : "
356 "source(%s), delimiter(%s), limit(%d)", source.c_str(), delimiter.c_str(), limit);
358 /*------ DEBUG LOG END ------*/
359 std::vector<std::string> words;
361 int end = source.size();
364 end = source.find(delimiter, begin);
365 if (end == std::string::npos) {
369 words.push_back(source.substr(begin, end - begin));
373 words.push_back(source.substr(begin, end - begin));
374 /*-------- DEBUG LOG --------*/
375 if (LOG_LV_DEBUG == logger_get_log_level(LOG_CAT_PACKET_EDIT)) {
376 LOGGER_PUT_LOG_DEBUG(LOG_CAT_PACKET_EDIT, 11,
377 "out_function : std::vector<std::string> packet_editor::split"
378 "(const std::string& source, const std::string& delimiter, int limit)");
380 /*------ DEBUG LOG END ------*/