demux: mp4: check handler before dereferencing sample entry
[vlc.git] / test / src / misc / keystore.c
blob36d07169e7d4d979af59edd108156e3f7b796f51
1 /*****************************************************************************
2 * keystore.c: test vlc_credential API
3 *****************************************************************************
4 * Copyright © 2016 VLC authors, VideoLAN and VideoLabs
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU Lesser General Public License as published by
8 * the Free Software Foundation; either version 2.1 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19 *****************************************************************************/
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24 #include <vlc/vlc.h>
26 #include "../../libvlc/test.h"
27 #include "../../../lib/libvlc_internal.h"
29 #include <vlc_common.h>
30 #include <vlc_plugin.h>
31 #include <vlc_interrupt.h>
32 #include <vlc_keystore.h>
33 #include <vlc_dialog.h>
34 #include <vlc_url.h>
35 #include <vlc_fs.h>
37 #include <assert.h>
39 struct cred
41 const char *psz_user;
42 const char *psz_pwd;
45 struct cred_res
47 const char *psz_user;
48 const char *psz_pwd;
49 const char *psz_realm;
50 const char *psz_authtype;
53 static const struct testcase
55 bool b_found;
56 const char *psz_url;
57 const char *psz_realm;
58 const char *psz_authtype;
59 struct cred_res result;
60 struct cred opt;
61 struct cred dialog;
62 bool b_dialog_store;
63 } testcases[] =
65 #define HTTP(path, realm) "http://"path, realm, "Basic"
66 #define SMB(path) "smb://"path, NULL, NULL
67 #define SFTP(path) "sftp://"path, NULL, NULL
68 #define WIPE_MEMORY_KEYSTORE \
69 { false, NULL, NULL, NULL, {}, {}, {}, false }
71 /* First tests use sftp protocol: no realm and results doesn't depend on
72 * path */
73 { true, SFTP("user1:pwd1@ex.com/testing/deprecated_url"),
74 { "user1", "pwd1", NULL, NULL }, {} , {}, false },
76 { true, SFTP("ex.com/testing/opt"),
77 { "user1", "pwd1", NULL, NULL }, { "user1", "pwd1" }, {}, false },
79 { true, SFTP("ex.com/testing/dial"),
80 { "user1", "pwd1", NULL, NULL }, {}, { "user1", "pwd1" }, false },
82 WIPE_MEMORY_KEYSTORE,
84 { true, SFTP("user1@ex.com/testing/url_dial"),
85 { "user1", "pwd1", NULL, NULL }, { NULL, NULL }, { NULL, "pwd1" }, false },
87 WIPE_MEMORY_KEYSTORE,
89 { true, SFTP("ex.com/testing/opt_dial"),
90 { "user1", "pwd1", NULL, NULL }, { "user1", NULL }, { NULL, "pwd1" }, false },
92 WIPE_MEMORY_KEYSTORE,
94 { true, SFTP("WRONG_USER@ex.com/testing/url_opt_dial"),
95 { "user1", "pwd1", NULL, NULL }, { "user1", NULL }, { NULL, "pwd1" }, false },
97 WIPE_MEMORY_KEYSTORE,
99 /* Order is important now since previously stored credentials could be
100 * found by future tests */
102 { true, SFTP("ex.com/testing/mem_ks_store"),
103 { "user1", "pwd1", NULL, NULL }, {}, { "user1", "pwd1" }, false },
105 { true, SFTP("ex.com/testing/mem_ks_find"),
106 { "user1", "pwd1", NULL, NULL }, {}, {}, false },
108 WIPE_MEMORY_KEYSTORE,
110 { false, SFTP("ex.com/testing/mem_ks_find"),
111 { "user1", "pwd1", NULL, NULL }, {}, {}, false },
113 WIPE_MEMORY_KEYSTORE,
115 /* Testing permanent keystore */
117 { true, SFTP("ex.com/testing/ks_store"),
118 { "user1", "pwd1", NULL, NULL }, {}, { "user1", "pwd1" }, true },
120 WIPE_MEMORY_KEYSTORE,
122 { true, SFTP("ex.com/testing/ks_find"),
123 { "user1", "pwd1", NULL, NULL }, {}, {}, false },
125 { true, SFTP("ex.com:2022/testing/ks_store"),
126 { "user2", "pwd2", NULL, NULL }, {}, { "user2", "pwd2" }, true },
128 WIPE_MEMORY_KEYSTORE,
130 { true, SFTP("user1@ex.com/testing/ks_find"),
131 { "user1", "pwd1", NULL, NULL }, {}, {}, false },
133 { true, SFTP("user2@ex.com:2022/testing/ks_find"),
134 { "user2", "pwd2", NULL, NULL }, {}, {}, false },
136 { false, SFTP("user2@wrong_host.com:2022/testing/ks_find"),
137 { "user2", "pwd2", NULL, NULL }, {}, {}, false },
139 { false, SFTP("user2@ex.com/testing/ks_find"),
140 { "user2", "pwd2", NULL, NULL }, {}, {}, false },
142 { false, SMB("user2@ex.com:2022/testing/ks_find"),
143 { "user2", "pwd2", NULL, NULL }, {}, {}, false },
145 WIPE_MEMORY_KEYSTORE,
147 { true, SFTP("ex.com/testing/opt_not_storing_ks"),
148 { "user3", "pwd3", NULL, NULL }, { "user3", "pwd3" }, {}, true },
150 WIPE_MEMORY_KEYSTORE,
152 { false, SFTP("ex.com/testing/opt_not_storing_ks"),
153 { "user3", "pwd3", NULL, NULL }, {}, {}, false },
155 WIPE_MEMORY_KEYSTORE,
157 /* Testing reusing http credentials rfc7617#2.2 */
159 { true, HTTP("ex.com/testing/good_path/ks_store_realm", "Realm"),
160 { "user4", "pwd4", "Realm", "Basic" }, {}, { "user4", "pwd4" }, true },
162 { false, HTTP("ex.com/testing/good_path/ks_find_realm", "Wrong realm"),
163 { "user4", "pwd4", "Wrong realm", "Basic" }, {}, {}, false },
165 { true, HTTP("ex.com/testing/good_path/ks_find_realm", "Realm"),
166 { "user4", "pwd4", "Realm", "Basic" }, {}, {}, false },
168 { true, HTTP("ex.com/testing/good_path/another_path/ks_find_realm", "Realm"),
169 { "user4", "pwd4", "Realm", "Basic" }, {}, {}, false },
171 { false, HTTP("ex.com/testing/wrong_path/ks_find_realm", "Realm"),
172 { "user4", "pwd4", "Realm", "Basic" }, {}, {}, false },
174 /* Testing reusing smb credentials */
176 { true, SMB("host/share/path1/path2/path3/ks_store"),
177 { "user5", "pwd5", NULL, NULL }, {}, { "user5", "pwd5" }, false },
179 { true, SMB("host/share/path4/ks_find"),
180 { "user5", "pwd5", NULL, NULL }, {}, {}, false },
182 { false, SMB("wrong_host/share/path4/ks_find"),
183 { "user5", "pwd5", NULL, NULL }, {}, {}, false },
185 { false, SMB("host/wrong_share/path4/ks_find"),
186 { "user5", "pwd5", NULL, NULL }, {}, {}, false },
188 WIPE_MEMORY_KEYSTORE,
190 /* Testing smb realm split */
192 { true, SMB("host/share/path1/ks_store"),
193 { "user6", "pwd6", "domain", NULL }, {}, { "domain;user6", "pwd6" }, true },
195 WIPE_MEMORY_KEYSTORE,
197 { true, SMB("host/share/path1/ks_store"),
198 { "user6", "pwd6", "domain", NULL }, {}, {}, false },
200 { true, SMB("domain;user6@host/share/path1/ks_find"),
201 { "user6", "pwd6", "domain", NULL }, {}, {}, false },
203 { false, SMB("wrong_domain;user6@host/share/path1/ks_find"),
204 { "user6", "pwd6", "wrong_domain", NULL }, {}, {}, false },
206 WIPE_MEMORY_KEYSTORE,
208 { false, "://invalid_url", NULL, NULL,
209 { "user1", "pwd1", NULL, NULL }, {}, { "user1", "pwd1" }, false },
211 { false, "/invalid_path", NULL, NULL,
212 { "user1", "pwd1", NULL, NULL }, {}, { "user1", "pwd1" }, false },
215 struct dialog_ctx
217 bool b_abort;
218 const struct testcase *p_test;
221 static void
222 display_login_cb(void *p_data, vlc_dialog_id *p_id, const char *psz_title,
223 const char *psz_text, const char *psz_default_username,
224 bool b_ask_store)
226 (void) psz_title;
227 (void) psz_text;
228 (void) psz_default_username;
229 (void) b_ask_store;
230 struct dialog_ctx *p_dialog_ctx = p_data;
231 const struct testcase *p_testcase = p_dialog_ctx->p_test;
233 const char *psz_user = p_testcase->dialog.psz_user != NULL ?
234 p_testcase->dialog.psz_user : psz_default_username;
235 if (!p_dialog_ctx->b_abort && psz_user != NULL
236 && p_testcase->dialog.psz_pwd != NULL)
238 vlc_dialog_id_post_login(p_id, psz_user, p_testcase->dialog.psz_pwd,
239 p_testcase->b_dialog_store);
240 p_dialog_ctx->b_abort = true;
242 else
243 vlc_dialog_id_dismiss(p_id);
246 static void
247 cancel_cb(void *p_data, vlc_dialog_id *p_id)
249 (void) p_data;
250 vlc_dialog_id_dismiss(p_id);
253 static void
254 test(vlc_object_t *p_obj, unsigned int i_id, const struct testcase *p_test)
256 printf("test(%u): url %s%s%s%s (%sexpected: %s:%s)\n", i_id, p_test->psz_url,
257 p_test->psz_realm != NULL ? " (realm: " : "",
258 p_test->psz_realm != NULL ? p_test->psz_realm : "",
259 p_test->psz_realm != NULL ? ")" : "",
260 p_test->b_found ? "" : "not ", p_test->result.psz_user,
261 p_test->result.psz_pwd);
263 const vlc_dialog_cbs cbs = {
264 .pf_display_login = display_login_cb,
265 .pf_cancel = cancel_cb,
267 struct dialog_ctx dialog_ctx = {
268 .b_abort = false,
269 .p_test = p_test,
271 vlc_dialog_provider_set_callbacks(p_obj, &cbs, &dialog_ctx);
273 const char *psz_opt_user = NULL, *psz_opt_pwd = NULL;
274 if (p_test->opt.psz_user != NULL)
276 psz_opt_user = "test-user";
277 var_SetString(p_obj, psz_opt_user, p_test->opt.psz_user);
279 if (p_test->opt.psz_pwd != NULL)
281 psz_opt_pwd = "test-pwd";
282 var_SetString(p_obj, psz_opt_pwd, p_test->opt.psz_pwd);
285 vlc_url_t url;
286 vlc_UrlParse(&url, p_test->psz_url);
288 vlc_credential credential;
289 vlc_credential_init(&credential, &url);
290 credential.psz_realm = p_test->psz_realm;
291 credential.psz_authtype = p_test->psz_authtype;
293 bool b_found = false;
294 while (vlc_credential_get(&credential, p_obj, psz_opt_user, psz_opt_pwd,
295 "test authentication", "this a test"))
297 bool realm_match = !p_test->result.psz_realm
298 || (credential.psz_realm
299 && strcmp(credential.psz_realm, p_test->result.psz_realm) == 0);
300 bool authtype_match = !p_test->result.psz_authtype
301 || (credential.psz_authtype
302 && strcmp(credential.psz_authtype, p_test->result.psz_authtype) == 0);
304 if (realm_match && authtype_match
305 && strcmp(credential.psz_username, p_test->result.psz_user) == 0
306 && strcmp(credential.psz_password, p_test->result.psz_pwd) == 0)
308 b_found = true;
309 break;
312 assert(b_found == p_test->b_found);
313 vlc_credential_store(&credential, p_obj);
315 vlc_UrlClean(&url);
316 vlc_credential_clean(&credential);
318 vlc_dialog_provider_set_callbacks(p_obj, NULL, NULL);
321 static libvlc_instance_t *
322 create_libvlc(int i_vlc_argc, const char *const *ppsz_vlc_argv)
324 libvlc_instance_t *p_libvlc = libvlc_new(i_vlc_argc, ppsz_vlc_argv);
325 assert(p_libvlc != NULL);
327 int i_ret;
328 i_ret = var_Create(p_libvlc->p_libvlc_int, "test-user", VLC_VAR_STRING);
329 assert(i_ret == VLC_SUCCESS);
330 i_ret = var_Create(p_libvlc->p_libvlc_int, "test-pwd", VLC_VAR_STRING);
331 assert(i_ret == VLC_SUCCESS);
333 return p_libvlc;
337 main(void)
339 test_init();
341 printf("creating tmp plaintext keystore file\n");
342 char psz_tmp_path[] = "/tmp/libvlc_XXXXXX";
343 int i_tmp_fd = -1;
344 i_tmp_fd = vlc_mkstemp(psz_tmp_path);
345 assert(i_tmp_fd != -1);
347 int i_vlc_argc = 4;
348 const char *ppsz_vlc_argv[i_vlc_argc];
349 ppsz_vlc_argv[0] = "--keystore";
350 ppsz_vlc_argv[1] = "file_plaintext,none";
351 ppsz_vlc_argv[2] = "--keystore-file";
352 ppsz_vlc_argv[3] = psz_tmp_path;
354 libvlc_instance_t *p_libvlc = create_libvlc(i_vlc_argc, ppsz_vlc_argv);
356 for (unsigned int i = 0; i < sizeof(testcases)/sizeof(*testcases); ++i)
358 if (testcases[i].psz_url == NULL)
360 printf("test(%u): wiping memory keystore\n", i);
361 libvlc_release(p_libvlc);
362 p_libvlc = create_libvlc(i_vlc_argc, ppsz_vlc_argv);
364 else
365 test(VLC_OBJECT(p_libvlc->p_libvlc_int), i, &testcases[i]);
368 libvlc_release(p_libvlc);
369 vlc_close(i_tmp_fd);
371 return 0;