OSDN Git Service

Generated Makefile.am.
[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     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));
92         }
93         // Remove request header field
94         else if (it->first == "unset") {
95             // "Header-Field-Name"
96             request.header(it->second, "");
97         }
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.
111                 } else {
112                     request.header(add_vector.at(0), add_vector.at(1));
113                 }
114             }
115         }
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);
131                     }
132                 }
133             }
134         }
135     }
136
137     /*
138      * Insert other protocol editor.
139      */
140
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.");
145     }
146     else {
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);
151     }
152
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)");
157     }
158     /*------ DEBUG LOG END ------*/
159 }
160
161 /*!
162  * Edit server message function.
163  */
164 void packet_editor::edit_server(char* server_msg, size_t& server_length)
165 {
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);
171     }
172     /*------ DEBUG LOG END ------*/
173
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));
188         }
189         // Remove request header field
190         else if (it->first == "unset") {
191             // "Header-Field-Name"
192             response.header(it->second, "");
193         }
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.
207                 } else {
208                     response.header(add_vector.at(0), add_vector.at(1));
209                 }
210             }
211         }
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);
227                     }
228                 }
229             }
230         }
231     }
232
233     /*
234      * Insert other protocol editor.
235      */
236
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.");
241     }
242     else {
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);
247     }
248
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)");
253     }
254     /*------ DEBUG LOG END ------*/
255 }
256
257 /*!
258  * Expand macro function.
259  *
260  * @param[in/out]   source  string
261  */
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());
268     }
269     /*------ DEBUG LOG END ------*/
270     int pos;
271
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));
278         }
279     }
280
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));
287         }
288     }
289
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));
294     }
295
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));
300     }
301
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));
306     }
307
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));
312     }
313
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)");
318     }
319     /*------ DEBUG LOG END ------*/
320 }
321
322 /*!
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.
327  *
328  * @param[in]   source  string
329  * @param[in]   delimiter   delimiter
330  * @param[in]   limit   max token
331  */
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);
339     }
340     /*------ DEBUG LOG END ------*/
341     std::vector<std::string> words;
342     int begin = 0;
343     int end   = source.size();
344     limit--;
345     while (limit != 0) {
346         end = source.find(delimiter, begin);
347         if (end == std::string::npos) {
348             end = source.size();
349             break;
350         }
351         words.push_back(source.substr(begin, end - begin));
352         begin = end + 1;
353         limit--;
354     }
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)");
361     }
362     /*------ DEBUG LOG END ------*/
363     return words;
364 }