1 /*
2  * ProFTPD - FTP server testsuite
3  * Copyright (c) 2015 The ProFTPD Project team
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA.
18  *
19  * As a special exemption, The ProFTPD Project team and other respective
20  * copyright holders give permission to link this program with OpenSSL, and
21  * distribute the resulting executable, without including the source code for
22  * OpenSSL in the source distribution.
23  */
24 
25 /* Encode API tests */
26 
27 #include "tests.h"
28 
29 static pool *p = NULL;
30 
set_up(void)31 static void set_up(void) {
32   if (p == NULL) {
33     p = permanent_pool = make_sub_pool(NULL);
34   }
35 
36 #ifdef PR_USE_NLS
37   encode_init();
38 #endif /* PR_USE_NLS */
39 
40   if (getenv("TEST_VERBOSE") != NULL) {
41     pr_trace_set_levels("encode", 1, 20);
42   }
43 }
44 
tear_down(void)45 static void tear_down(void) {
46   if (getenv("TEST_VERBOSE") != NULL) {
47     pr_trace_set_levels("encode", 0, 0);
48   }
49 
50 #ifdef PR_USE_NLS
51   encode_free();
52 #endif /* PR_USE_NLS */
53 
54   if (p) {
55     destroy_pool(p);
56     p = permanent_pool = NULL;
57   }
58 }
59 
60 #ifdef PR_USE_NLS
START_TEST(encode_encode_str_test)61 START_TEST (encode_encode_str_test) {
62   char *res;
63   const char *in_str, junk[1024];
64   size_t in_len, out_len = 0;
65 
66   res = pr_encode_str(NULL, NULL, 0, NULL);
67   fail_unless(res == NULL, "Failed to handle null arguments");
68   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
69     strerror(errno), errno);
70 
71   res = pr_encode_str(p, NULL, 0, NULL);
72   fail_unless(res == NULL, "Failed to handle null input string");
73   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
74     strerror(errno), errno);
75 
76   in_str = "OK";
77   in_len = 2;
78   res = pr_encode_str(p, in_str, in_len, NULL);
79   fail_unless(res == NULL, "Failed to handle null output string len");
80   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
81     strerror(errno), errno);
82 
83   res = pr_encode_str(p, in_str, in_len, &out_len);
84   fail_unless(res != NULL, "Failed to encode '%s': %s", in_str,
85     strerror(errno));
86   fail_unless(strcmp(res, in_str) == 0, "Expected '%s', got '%s'", in_str,
87     res);
88 
89   in_str = junk;
90   in_len = sizeof(junk);
91   res = pr_encode_str(p, in_str, in_len, &out_len);
92   fail_unless(res == NULL, "Failed to handle bad input");
93   fail_unless(errno == EILSEQ, "Expected EILSEQ (%d), got %s (%d)", EILSEQ,
94     strerror(errno), errno);
95 }
96 END_TEST
97 
START_TEST(encode_decode_str_test)98 START_TEST (encode_decode_str_test) {
99   char *res;
100   const char *in_str, junk[1024];
101   size_t in_len, out_len = 0;
102 
103   res = pr_decode_str(NULL, NULL, 0, NULL);
104   fail_unless(res == NULL, "Failed to handle null arguments");
105   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
106     strerror(errno), errno);
107 
108   res = pr_decode_str(p, NULL, 0, NULL);
109   fail_unless(res == NULL, "Failed to handle null input string");
110   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
111     strerror(errno), errno);
112 
113   in_str = "OK";
114   in_len = 2;
115   res = pr_decode_str(p, in_str, in_len, NULL);
116   fail_unless(res == NULL, "Failed to handle null output string len");
117   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
118     strerror(errno), errno);
119 
120   res = pr_decode_str(p, in_str, in_len, &out_len);
121   fail_unless(res != NULL, "Failed to decode '%s': %s", in_str,
122     strerror(errno));
123   fail_unless(strcmp(res, in_str) == 0, "Expected '%s', got '%s'", in_str,
124     res);
125 
126   in_str = junk;
127   in_len = sizeof(junk);
128   res = pr_encode_str(p, in_str, in_len, &out_len);
129   fail_unless(res == NULL, "Failed to handle bad input");
130   fail_unless(errno == EILSEQ, "Expected EILSEQ (%d), got %s (%d)", EILSEQ,
131     strerror(errno), errno);
132 }
133 END_TEST
134 
START_TEST(encode_charset_test)135 START_TEST (encode_charset_test) {
136   int res;
137   const char *charset, *encoding;
138 
139   charset = pr_encode_get_charset();
140   fail_unless(charset != NULL, "Failed to get current charset: %s",
141     strerror(errno));
142 
143   res = pr_encode_is_utf8(NULL);
144   fail_unless(res == -1, "Failed to handle null arguments");
145   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
146     strerror(errno), errno);
147 
148   charset = "utf8";
149   res = pr_encode_is_utf8(charset);
150   fail_unless(res == TRUE, "Expected TRUE for '%s', got %d", charset, res);
151 
152   charset = "utf-8";
153   res = pr_encode_is_utf8(charset);
154   fail_unless(res == TRUE, "Expected TRUE for '%s', got %d", charset, res);
155 
156   charset = "ascii";
157   res = pr_encode_is_utf8(charset);
158   fail_unless(res == FALSE, "Expected FALSE for '%s', got %d", charset, res);
159 
160   res = pr_encode_set_charset_encoding(NULL, NULL);
161   fail_unless(res < 0, "Failed to handle null arguments");
162   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
163     strerror(errno), errno);
164 
165   charset = "us-ascii";
166   res = pr_encode_set_charset_encoding(charset, NULL);
167   fail_unless(res < 0, "Failed to handle null encoding");
168   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
169     strerror(errno), errno);
170 
171   encoding = "utf-8";
172   res = pr_encode_set_charset_encoding(charset, encoding);
173   fail_unless(res == 0, "Failed to set charset '%s', encoding '%s': %s",
174     charset, encoding, strerror(errno));
175 
176   charset = "foo";
177   res = pr_encode_set_charset_encoding(charset, encoding);
178   fail_unless(res < 0, "Failed to handle bad charset '%s'", charset);
179   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
180     strerror(errno), errno);
181 
182   charset = "us-ascii";
183   encoding = "foo";
184   res = pr_encode_set_charset_encoding(charset, encoding);
185   fail_unless(res < 0, "Failed to handle bad encoding '%s'", encoding);
186   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
187     strerror(errno), errno);
188 }
189 END_TEST
190 
START_TEST(encode_encoding_test)191 START_TEST (encode_encoding_test) {
192   int res;
193   const char *encoding;
194 
195   res = pr_encode_enable_encoding(NULL);
196   fail_unless(res < 0, "Failed to handle null arguments");
197   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
198     strerror(errno), errno);
199 
200   encoding = "utf-8";
201   res = pr_encode_enable_encoding(encoding);
202   fail_unless(res == 0, "Failed to enable encoding '%s': %s", encoding,
203     strerror(errno));
204 
205   encoding = "iso-8859-1";
206   res = pr_encode_enable_encoding(encoding);
207   fail_unless(res == 0, "Failed to enable encoding '%s': %s", encoding,
208     strerror(errno));
209 
210   encoding = "foo";
211   res = pr_encode_enable_encoding(encoding);
212   fail_unless(res < 0, "Failed to handle bad encoding '%s'", encoding);
213   fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL,
214     strerror(errno), errno);
215 
216   pr_encode_disable_encoding();
217 
218   encoding = "utf-8";
219   res = pr_encode_enable_encoding(encoding);
220   fail_unless(res == 0, "Failed to enable encoding '%s': %s", encoding,
221     strerror(errno));
222 
223   encoding = pr_encode_get_encoding();
224   fail_unless(encoding != NULL, "Failed to get encoding: %s", strerror(errno));
225   fail_unless(strcasecmp(encoding, "utf-8") == 0,
226     "Expected 'utf-8', got '%s'", encoding);
227 }
228 END_TEST
229 
START_TEST(encode_policy_test)230 START_TEST (encode_policy_test) {
231   unsigned long res;
232 
233   res = pr_encode_get_policy();
234   fail_unless(res == 0, "Expected policy 0, got %lu", res);
235 
236   res = pr_encode_set_policy(7);
237   fail_unless(res == 0, "Expected policy 0, got %lu", res);
238 
239   res = pr_encode_get_policy();
240   fail_unless(res == 7, "Expected policy 7, got %lu", res);
241 
242   (void) pr_encode_set_policy(0);
243 }
244 END_TEST
245 
START_TEST(encode_supports_telnet_iac_test)246 START_TEST (encode_supports_telnet_iac_test) {
247   register unsigned int i;
248   int res;
249   const char *charset, *encoding;
250   const char *non_iac_encodings[] = {
251     "cp1251",
252     "cp866",
253     "iso-8859-1",
254     "koi8-r",
255     "windows-1251",
256     NULL
257   };
258 
259   res = pr_encode_supports_telnet_iac();
260   fail_unless(res == TRUE, "Expected TRUE, got %d", res);
261 
262   charset = "us-ascii";
263 
264   for (i = 0; non_iac_encodings[i]; i++) {
265     encoding = non_iac_encodings[i];
266 
267     res = pr_encode_set_charset_encoding(charset, encoding);
268     fail_unless(res == 0, "Failed to set charset '%s', encoding '%s': %s",
269       charset, encoding, strerror(errno));
270 
271     res = pr_encode_supports_telnet_iac();
272     fail_unless(res == FALSE, "Expected FALSE, got %d", res);
273   }
274 
275   encoding = "utf-8";
276   res = pr_encode_set_charset_encoding(charset, encoding);
277   fail_unless(res == 0, "Failed to set charset '%s', encoding '%s': %s",
278     charset, encoding, strerror(errno));
279 }
280 END_TEST
281 #endif /* PR_USE_NLS */
282 
tests_get_encode_suite(void)283 Suite *tests_get_encode_suite(void) {
284   Suite *suite;
285   TCase *testcase;
286 
287   suite = suite_create("encode");
288 
289   testcase = tcase_create("base");
290   tcase_add_checked_fixture(testcase, set_up, tear_down);
291 
292 #ifdef PR_USE_NLS
293   tcase_add_test(testcase, encode_encode_str_test);
294   tcase_add_test(testcase, encode_decode_str_test);
295   tcase_add_test(testcase, encode_charset_test);
296   tcase_add_test(testcase, encode_encoding_test);
297   tcase_add_test(testcase, encode_policy_test);
298   tcase_add_test(testcase, encode_supports_telnet_iac_test);
299 #endif /* PR_USE_NLS */
300 
301   suite_add_tcase(suite, testcase);
302   return suite;
303 }
304