1 /***************************************************************************
2 * Copyright (c) 2009-2010 Open Information Security Foundation
3 * Copyright (c) 2010-2013 Qualys, Inc.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * - Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12
13 * - Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16
17 * - Neither the name of the Qualys, Inc. nor the names of its
18 * contributors may be used to endorse or promote products derived from
19 * this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 * HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 ***************************************************************************/
33
34 /**
35 * @file
36 * @author Ivan Ristic <ivanr@webkreator.com>
37 */
38
39 #include "htp_config_auto.h"
40
41 #include "htp_private.h"
42
43 /**
44 * Transcode all parameters supplied in the table.
45 *
46 * @param[in] connp
47 * @param[in] params
48 * @param[in] destroy_old
49 */
htp_transcode_params(htp_connp_t * connp,htp_table_t ** params,int destroy_old)50 int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_old) {
51 htp_table_t *input_params = *params;
52
53 // No transcoding unless necessary
54 if ((connp->cfg->internal_encoding == NULL)||(connp->cfg->request_encoding == NULL)) return HTP_OK;
55
56 // Create a new table that will hold transcoded parameters
57 htp_table_t *output_params = htp_table_create(htp_table_size(input_params));
58 if (output_params == NULL) return HTP_ERROR;
59
60 // Initialize iconv
61 iconv_t cd = iconv_open(connp->cfg->internal_encoding, connp->cfg->request_encoding);
62 if (cd == (iconv_t) -1) {
63 htp_table_destroy(output_params);
64 return HTP_ERROR;
65 }
66
67 #if (_LIBICONV_VERSION >= 0x0108 && HAVE_ICONVCTL)
68 int iconv_param = 0;
69 iconvctl(cd, ICONV_SET_TRANSLITERATE, &iconv_param);
70 iconv_param = 1;
71 iconvctl(cd, ICONV_SET_DISCARD_ILSEQ, &iconv_param);
72 #endif
73
74 // Convert the parameters, one by one
75 bstr *name = NULL;
76 bstr *value = NULL;
77 for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
78 value = htp_table_get_index(input_params, i, &name);
79
80 bstr *new_name = NULL, *new_value = NULL;
81
82 // Convert name
83 htp_transcode_bstr(cd, name, &new_name);
84 if (new_name == NULL) {
85 iconv_close(cd);
86
87 bstr *b = NULL;
88 for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
89 b = htp_table_get_index(output_params, j, NULL);
90 bstr_free(b);
91 }
92
93 htp_table_destroy(output_params);
94 return HTP_ERROR;
95 }
96
97 // Convert value
98 htp_transcode_bstr(cd, value, &new_value);
99 if (new_value == NULL) {
100 bstr_free(new_name);
101 iconv_close(cd);
102
103 bstr *b = NULL;
104 for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
105 b = htp_table_get_index(output_params, j, NULL);
106 bstr_free(b);
107 }
108
109 htp_table_destroy(output_params);
110 return HTP_ERROR;
111 }
112
113 // Add to new table
114 htp_table_addn(output_params, new_name, new_value);
115 }
116
117 // Replace the old parameter table
118 *params = output_params;
119
120 // Destroy the old parameter table if necessary
121 if (destroy_old) {
122 bstr *b = NULL;
123 for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
124 b = htp_table_get_index(input_params, i, NULL);
125 bstr_free(b);
126 }
127
128 htp_table_destroy(input_params);
129 }
130
131 iconv_close(cd);
132
133 return HTP_OK;
134 }
135
136 /**
137 * Transcode one bstr.
138 *
139 * @param[in] cd
140 * @param[in] input
141 * @param[in] output
142 */
htp_transcode_bstr(iconv_t cd,bstr * input,bstr ** output)143 int htp_transcode_bstr(iconv_t cd, bstr *input, bstr **output) {
144 // Reset conversion state for every new string
145 iconv(cd, NULL, 0, NULL, 0);
146
147 bstr_builder_t *bb = NULL;
148
149 const size_t buflen = 10;
150 unsigned char *buf = malloc(buflen);
151 if (buf == NULL) {
152 return HTP_ERROR;
153 }
154
155 const char *inbuf = (const char *)bstr_ptr(input);
156 size_t inleft = bstr_len(input);
157 char *outbuf = (char *)buf;
158 size_t outleft = buflen;
159
160 int loop = 1;
161 while (loop) {
162 loop = 0;
163
164 if (iconv(cd, (ICONV_CONST char **)&inbuf, &inleft, (char **)&outbuf, &outleft) == (size_t) - 1) {
165 if (errno == E2BIG) {
166 // Create bstr builder on-demand
167 if (bb == NULL) {
168 bb = bstr_builder_create();
169 if (bb == NULL) {
170 free(buf);
171 return HTP_ERROR;
172 }
173 }
174
175 // The output buffer is full
176 bstr_builder_append_mem(bb, buf, buflen - outleft);
177
178 outbuf = (char *)buf;
179 outleft = buflen;
180
181 // Continue in the loop, as there's more work to do
182 loop = 1;
183 } else {
184 // Error
185 if (bb != NULL) bstr_builder_destroy(bb);
186 free(buf);
187 return HTP_ERROR;
188 }
189 }
190 }
191
192 if (bb != NULL) {
193 bstr_builder_append_mem(bb, buf, buflen - outleft);
194 *output = bstr_builder_to_str(bb);
195 bstr_builder_destroy(bb);
196 if (*output == NULL) {
197 free(buf);
198 return HTP_ERROR;
199 }
200 } else {
201 *output = bstr_dup_mem(buf, buflen - outleft);
202 if (*output == NULL) {
203 free(buf);
204 return HTP_ERROR;
205 }
206 }
207
208 free(buf);
209
210 return HTP_OK;
211 }
212