OSDN Git Service

Ignore packet of not first HTTP header message.
[ultramonkey-l7/sslproxy.git] / src / packet_editor.cpp
1 /*
2  * @file  packet_editor.cpp
3  * @brief Packet Editor Header
4  *
5  * Copyright (C) 2009  NTT COMWARE Corporation.
6  *
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.
11  *
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.
16  *
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
20  * 02110-1301 USA
21  *
22  **********************************************************************/
23
24 #include <boost/regex.hpp>
25 #include "packet_editor.h"
26 #include "sslproxy.h"
27 #include "sslproxyserver.h"
28 #include "sslproxysession.h"
29
30 /*!
31  * Packet editor constructor.
32  */
33 packet_editor::packet_editor(const sslproxy_session* session)
34 {
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)");
39     }
40     /*------ DEBUG LOG END ------*/
41
42     this->session = session;
43
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)");
48     }
49     /*------ DEBUG LOG END ------*/
50 }
51
52 /*!
53  * Packet editor destructor.
54  */
55 packet_editor::~packet_editor()
56 {
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)");
61     }
62     /*------ DEBUG LOG END ------*/
63 }
64
65 /*!
66  * Edit client message function.
67  */
68 void packet_editor::edit_client(char* client_msg, size_t& client_length)
69 {
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);
75     }
76     /*------ DEBUG LOG END ------*/
77
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
84     // Ignore when client_msg is not HTTP message
85     if (request.method().empty())
86         goto packet_edit_out;
87
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));
97         }
98         // Remove request header field
99         else if (it->first == "unset") {
100             // "Header-Field-Name"
101             request.header(it->second, "");
102         }
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.
116                 } else {
117                     request.header(add_vector.at(0), add_vector.at(1));
118                 }
119             }
120         }
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);
136                     }
137                 }
138             }
139         }
140     }
141
142     /*
143      * Insert other protocol editor.
144      */
145
146 packet_edit_out:
147
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.");
153         }
154         else {
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);
159         }
160     }
161
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)");
166     }
167     /*------ DEBUG LOG END ------*/
168 }
169
170 /*!
171  * Edit server message function.
172  */
173 void packet_editor::edit_server(char* server_msg, size_t& server_length)
174 {
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);
180     }
181     /*------ DEBUG LOG END ------*/
182
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));
188
189     // Ignore when server_msg is not HTTP message
190     if (response.http_version().empty())
191         goto packet_edit_out;
192
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));
202         }
203         // Remove request header field
204         else if (it->first == "unset") {
205             // "Header-Field-Name"
206             response.header(it->second, "");
207         }
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.
221                 } else {
222                     response.header(add_vector.at(0), add_vector.at(1));
223                 }
224             }
225         }
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);
241                     }
242                 }
243             }
244         }
245     }
246
247     /*
248      * Insert other protocol editor.
249      */
250
251 packet_edit_out:
252
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.");
258         }
259         else {
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);
264         }
265     }
266
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)");
271     }
272     /*------ DEBUG LOG END ------*/
273 }
274
275 /*!
276  * Expand macro function.
277  *
278  * @param[in/out]   source  string
279  */
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());
286     }
287     /*------ DEBUG LOG END ------*/
288     int pos;
289
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));
296         }
297     }
298
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));
305         }
306     }
307
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));
312     }
313
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));
318     }
319
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));
324     }
325
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));
330     }
331
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)");
336     }
337     /*------ DEBUG LOG END ------*/
338 }
339
340 /*!
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.
345  *
346  * @param[in]   source  string
347  * @param[in]   delimiter   delimiter
348  * @param[in]   limit   max token
349  */
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);
357     }
358     /*------ DEBUG LOG END ------*/
359     std::vector<std::string> words;
360     int begin = 0;
361     int end   = source.size();
362     limit--;
363     while (limit != 0) {
364         end = source.find(delimiter, begin);
365         if (end == std::string::npos) {
366             end = source.size();
367             break;
368         }
369         words.push_back(source.substr(begin, end - begin));
370         begin = end + 1;
371         limit--;
372     }
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)");
379     }
380     /*------ DEBUG LOG END ------*/
381     return words;
382 }