blob: 8d50145d61fc09ae87e25894e79c7caebad1b9ea [file] [log] [blame]
Michal Vaskoba9f3582023-02-22 10:26:32 +01001/**
2 * @file test_client_ssh.c
3 * @author David Sedlák <xsedla1d@stud.fit.vutbr.cz>
4 * @brief client SSH test
5 *
6 * Copyright (c) 2018 CESNET, z.s.p.o.
7 *
8 * This source code is licensed under BSD 3-Clause License (the "License").
9 * You may not use this file except in compliance with the License.
10 * You may obtain a copy of the License at
11 *
12 * https://opensource.org/licenses/BSD-3-Clause
13 */
14
15#define _GNU_SOURCE
16
Michal Vaskob83a3fa2021-05-26 09:53:42 +020017#include <errno.h>
18#include <setjmp.h>
David Sedlákddde4492018-09-30 21:34:38 +020019#include <stdio.h>
20#include <stdlib.h>
David Sedlákddde4492018-09-30 21:34:38 +020021#include <sys/socket.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020022#include <sys/types.h>
David Sedlákddde4492018-09-30 21:34:38 +020023
24#include <cmocka.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020025#include <config.h>
David Sedlákddde4492018-09-30 21:34:38 +020026#include <libyang/libyang.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020027#include <log.h>
David Sedlákddde4492018-09-30 21:34:38 +020028#include <session_client.h>
Fred Gan3a736e02021-01-04 17:59:38 +080029#include <session_client_ch.h>
30#include <session_p.h>
David Sedlákddde4492018-09-30 21:34:38 +020031#include "tests/config.h"
32
David Sedlákddde4492018-09-30 21:34:38 +020033#include <libssh/callbacks.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020034#include <libssh/libssh.h>
David Sedlákddde4492018-09-30 21:34:38 +020035#include <libssh/server.h>
36
37static int
38ssh_hostkey_check_clb(const char *hostname, ssh_session session, void *priv)
39{
40 (void)hostname;
41 (void)session;
42 (void)priv;
43
44 return 0;
45}
46
47static int
48setup_f(void **state)
49{
50 (void)state;
51 int ret;
52
53 nc_verbosity(NC_VERB_VERBOSE);
54
55 ret = nc_client_ssh_set_username("username");
56 assert_int_equal(ret, 0);
Fred Gan3a736e02021-01-04 17:59:38 +080057 ret = nc_client_ssh_ch_set_username("ch_username");
58 assert_int_equal(ret, 0);
David Sedlákddde4492018-09-30 21:34:38 +020059 nc_client_ssh_set_auth_hostkey_check_clb(ssh_hostkey_check_clb, NULL);
60
61 return 0;
62}
63
64static int
65teardown_f(void **state)
66{
67 (void)state;
68 return 0;
69}
70
71MOCK int
72__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
73{
74 (void)sockfd;
75 (void)addr;
76 (void)addrlen;
77
78 return (int)mock();
79}
80
81MOCK int
82__wrap_ssh_connect(ssh_session session)
83{
84 (void)session;
85
86 /* set support of all authentication methods by fake server */
87 ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
88 return (int)mock();
89}
90
91MOCK int
92__wrap_ssh_userauth_none(ssh_session session, const char *username)
93{
94 (void)session;
95 (void)username;
96
97 return (int)mock();
98}
99
100MOCK int
101__wrap_ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods)
102{
103 (void)session;
104 (void)user;
105 (void)submethods;
106
107 return (int)mock();
108}
109
110MOCK int
111__wrap_ssh_is_connected(ssh_session session)
112{
113 (void)session;
114
115 return (int)mock();
116}
117
118MOCK int
119__wrap_ssh_channel_open_session(ssh_channel channel)
120{
121 (void)channel;
122
123 return (int)mock();
124}
125
126MOCK int
127__wrap_ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem)
128{
129 (void)channel;
130 (void)subsystem;
131
132 return (int)mock();
133}
134
135MOCK int
136__wrap_ssh_channel_is_closed(ssh_channel channel)
137{
138 (void)channel;
139
140 return 0;
141}
142
143MOCK int
144__wrap_ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
145{
146 (void)channel;
147 (void)data;
148
149 return len;
150}
151
152MOCK int
153__wrap_ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
154{
155 (void)channel;
156 (void)timeout;
157 (void)is_stderr;
158
159 return (int)mock();
160}
161
162MOCK int
163__wrap_ssh_userauth_password(ssh_session session, const char *username, const char *password)
164{
165 (void)session;
166 check_expected(password);
167 check_expected(username);
168
David Sedlákddde4492018-09-30 21:34:38 +0200169 return (int)mock();
170}
171
172MOCK int
173__wrap_nc_handshake_io(struct nc_session *session)
174{
175 (void)session;
176
177 return (int)mock();
178}
179
180MOCK int
181__wrap_nc_ctx_check_and_fill(struct nc_session *session)
182{
183 (void)session;
184
185 return (int)mock();
186}
187
David Sedlák77acc202018-10-08 21:44:14 +0200188MOCK int
189__wrap_ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey)
190{
191 (void)session;
192 (void)username;
193 (void)pubkey;
194
195 return (int)mock();
196}
197
198MOCK int
199__wrap_ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey)
200{
201 (void)session;
202 (void)username;
203 (void)privkey;
204
205 return (int)mock();
206}
207
Fred Gan3a736e02021-01-04 17:59:38 +0800208MOCK int
209__wrap_nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
210{
211 (void)address;
212 (void)port;
213 (void)ka;
214
215 return (int)mock();
216}
217
218MOCK int
219__wrap_nc_sock_accept_binds(struct nc_bind *binds, uint16_t bind_count, int timeout, char **host, uint16_t *port, uint16_t *idx)
220{
221 (void)binds;
222 (void)bind_count;
223 (void)timeout;
224 (void)host;
225 (void)port;
226
227 *idx = 0;
228 return (int)mock();
229}
230
231MOCK struct nc_session *
232__wrap_nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout)
233{
234 (void)sock;
235 (void)host;
236 (void)port;
237 (void)ctx;
238 (void)timeout;
239
240 return mock_ptr_type(struct nc_session *);
241}
242
David Sedlákddde4492018-09-30 21:34:38 +0200243static int
244test_hostkey_clb(const char *hostname, ssh_session session, void *priv)
245{
246 (void)hostname;
247 (void)session;
248 (void)priv;
249
250 return 0;
251}
252
253static void
254test_nc_client_ssh_setting_auth_hostkey_check_clb(void **state)
255{
256 (void)state;
257 int (*ret_f)(const char *hostname, ssh_session session, void *priv);
258 char *priv_data_ret;
259
260 /* ssh_hostkey_check_clb is set in setup_f */
261 nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
262 assert_ptr_equal(ret_f, ssh_hostkey_check_clb);
263 assert_null(priv_data_ret);
264
265 /* set different callback and private data */
266 nc_client_ssh_set_auth_hostkey_check_clb(test_hostkey_clb, "DATA");
267 nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
268 assert_ptr_equal(ret_f, test_hostkey_clb);
269 assert_string_equal(priv_data_ret, "DATA");
270}
271
272char *
273test_pwd_clb1(const char *username, const char *hostname, void *priv)
274{
275 char *pass, *pass_to_return;
276
277 check_expected(username);
278 check_expected(hostname);
279 check_expected(priv);
280
281 pass = (char *)mock();
282 pass_to_return = malloc(sizeof *pass * (strlen(pass) + 1));
283 strcpy(pass_to_return, pass);
284
285 return pass_to_return;
286}
287
288char *
289test_pwd_clb2(const char *username, const char *hostname, void *priv)
290{
291 (void)username;
292 (void)hostname;
293 (void)priv;
294
295 return 0;
296}
297
298static void
299test_nc_client_ssh_setting_auth_password_clb(void **state)
300{
301 (void)state;
302 char *(*ret_f)(const char *username, const char *hostname, void *priv);
303 char *priv_data_ret;
304
305 /* set callback */
306 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "DATA");
307 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
308 assert_ptr_equal(test_pwd_clb1, ret_f);
309 assert_string_equal("DATA", priv_data_ret);
310
311 /* set different callback */
312 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, "NEW DATA");
313 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
314 assert_ptr_equal(test_pwd_clb2, ret_f);
315 assert_string_equal("NEW DATA", priv_data_ret);
316}
317
318char *
319test_inter_clb1(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
320{
321 (void)auth_name;
322 (void)instruction;
323 (void)prompt;
324 (void)echo;
325 (void)priv;
326
327 return 0;
328}
329
330char *
331test_inter_clb2(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
332{
333 (void)auth_name;
334 (void)instruction;
335 (void)prompt;
336 (void)echo;
337 (void)priv;
338
339 return 0;
340}
341
342static void
343test_nc_client_ssh_setting_auth_interactive_clb(void **state)
344{
345 (void)state;
346 char *(*ret_f)(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv);
347 char *priv_data_ret;
348
349 /* set callback */
350 nc_client_ssh_set_auth_interactive_clb(test_inter_clb1, "DATA");
351 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
352 assert_ptr_equal(test_inter_clb1, ret_f);
353 assert_string_equal("DATA", priv_data_ret);
354
355 /* set diferent callback */
356 nc_client_ssh_set_auth_interactive_clb(test_inter_clb2, "NEW DATA");
357 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
358 assert_ptr_equal(test_inter_clb2, ret_f);
359 assert_string_equal("NEW DATA", priv_data_ret);
360}
361
362char *
363test_passphrase_clb1(const char *privkey_path, void *priv)
364{
365 (void)privkey_path;
366 (void)priv;
367
368 return 0;
369}
370
371char *
372test_passphrase_clb2(const char *privkey_path, void *priv)
373{
374 (void)privkey_path;
375 (void)priv;
376
377 return 0;
378}
379
380static void
381test_nc_client_ssh_setting_auth_privkey_passphrase_clb(void **state)
382{
383 (void)state;
384 char *(*ret_f)(const char *privkey_path, void *priv);
385 char *priv_data_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200386
David Sedlákddde4492018-09-30 21:34:38 +0200387 /* set first callback */
388 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb1, "DATA");
389 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
390 assert_ptr_equal(ret_f, test_passphrase_clb1);
391 assert_string_equal("DATA", priv_data_ret);
392
393 /* set different callback */
394 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb2, "NEW DATA");
395 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
396 assert_ptr_equal(ret_f, test_passphrase_clb2);
397 assert_string_equal("NEW DATA", priv_data_ret);
398}
399
400static void
401test_nc_client_ssh_adding_keypair(void **state)
402{
403 (void)state;
404 int ret;
405 const char *pubkey1, *pubkey2;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200406
David Sedlákddde4492018-09-30 21:34:38 +0200407 /* at the beginning keypair count should be 0 */
408 ret = nc_client_ssh_get_keypair_count();
409 assert_int_equal(ret, 0);
410
411 /* add first key pair */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200412 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_ecdsa.pub", TESTS_DIR "/data/key_ecdsa");
David Sedlákddde4492018-09-30 21:34:38 +0200413 assert_int_equal(ret, 0);
414 ret = nc_client_ssh_get_keypair_count();
415 assert_int_equal(ret, 1);
416
417 /* add second keypair */
418 ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
419 assert_int_equal(ret, 0);
420 ret = nc_client_ssh_get_keypair_count();
421 assert_int_equal(ret, 2);
422 ret = nc_client_ssh_get_keypair(1, &pubkey1, &pubkey2);
423 assert_int_equal(ret, 0);
424 assert_string_equal(pubkey1, "key_pub");
425 assert_string_equal(pubkey2, "key_priv");
426
427 /* delete first keypair */
428 ret = nc_client_ssh_del_keypair(0);
429 assert_int_equal(ret, 0);
430 ret = nc_client_ssh_get_keypair_count();
431 assert_int_equal(ret, 1);
432 /* try to get deleted keypair */
433 ret = nc_client_ssh_get_keypair(5, &pubkey1, &pubkey2);
434 assert_int_equal(ret, -1);
435
436 /* try to add keypair that is already set */
437 ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
438 assert_int_equal(ret, -1);
439 ret = nc_client_ssh_get_keypair_count();
440 assert_int_equal(ret, 1);
441
442 /* try to delete keypair with id that is not used */
443 ret = nc_client_ssh_del_keypair(42);
444 assert_int_equal(ret, -1);
445 ret = nc_client_ssh_get_keypair_count();
446 assert_int_equal(ret, 1);
447
448 /* remove remaining keypairs */
449 ret = nc_client_ssh_del_keypair(0);
450 assert_int_equal(ret, 0);
451 ret = nc_client_ssh_get_keypair_count();
452 assert_int_equal(ret, 0);
453}
454
455static void
456test_nc_client_ssh_setting_auth_pref(void **state)
457{
458 (void)state;
459 int ret;
460
David Sedlákaae4df32018-10-08 22:27:22 +0200461 /* initiate client, must be called in first test */
David Sedlákddde4492018-09-30 21:34:38 +0200462 nc_client_init();
463
464 /* check default prefference settings according to documentation */
465 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
roman41a11e42022-06-22 09:27:08 +0200466 assert_int_equal(ret, 1);
David Sedlákddde4492018-09-30 21:34:38 +0200467 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
468 assert_int_equal(ret, 2);
469 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
roman41a11e42022-06-22 09:27:08 +0200470 assert_int_equal(ret, 3);
David Sedlákddde4492018-09-30 21:34:38 +0200471
472 /* try to set prefetence of non existing method */
473 nc_client_ssh_set_auth_pref(42, 22);
474
475 /* try to get preference of non existing method */
476 ret = nc_client_ssh_get_auth_pref(42);
477 assert_int_equal(ret, 0);
478
479 /* change values of all methods and check if they actually changed */
480 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 9);
481 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
482 assert_int_equal(ret, 9);
483
484 /* negative value should be set as -1 */
485 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -5);
486 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
487 assert_int_equal(ret, -1);
488
489 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 11);
490 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
491 assert_int_equal(ret, 11);
492}
493
494static void
495test_nc_client_ssh_setting_username(void **state)
496{
497 (void)state;
498 int ret;
499 const char *username_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200500
David Sedlákddde4492018-09-30 21:34:38 +0200501 username_ret = nc_client_ssh_get_username();
502 /* username is set to "username" in setup_f */
503 assert_string_equal(username_ret, "username");
504
505 /* set new username and check if it changes */
506 ret = nc_client_ssh_set_username("new_username");
507 assert_int_equal(ret, 0);
508 username_ret = nc_client_ssh_get_username();
509 assert_string_equal(username_ret, "new_username");
510}
511
512static void
513test_nc_connect_ssh_interactive_succesfull(void **state)
514{
515 (void)state;
516 struct nc_session *session;
517
518 /* set authentication method to use interactive authentication */
519 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
520 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
521 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
522
523 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 20);
524
525 /* prepare return values for functions used by nc_connect_ssh */
526 will_return(__wrap_connect, 0);
527 will_return(__wrap_ssh_connect, 0);
528 will_return(__wrap_ssh_userauth_none, 1);
529
530 will_return(__wrap_ssh_userauth_kbdint, 0);
531 will_return(__wrap_ssh_is_connected, 1);
532 will_return(__wrap_ssh_is_connected, 1);
533
534 will_return(__wrap_ssh_channel_open_session, 0);
535 will_return(__wrap_ssh_channel_request_subsystem, 0);
536
537 will_return(__wrap_nc_handshake_io, 3);
538 will_return(__wrap_nc_ctx_check_and_fill, 0);
539
540 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
541 assert_non_null(session);
542
Michal Vasko0ab3a662021-07-26 12:17:41 +0200543 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200544 nc_session_free(session, NULL);
545}
546
547static void
548test_nc_connect_ssh_password_succesfull(void **state)
549{
550 (void)state;
551 struct nc_session *session;
552
553 /* set authentication method to use password authentication */
554 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 1);
555 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
556 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
557
558 /* set authentication callback */
559 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "private_data");
560 will_return(test_pwd_clb1, "secret password");
561 /* set values that are expected as parameters for authentication callback */
562 expect_string(test_pwd_clb1, username, "username");
563 expect_string(test_pwd_clb1, hostname, "127.0.0.1");
564 expect_string(test_pwd_clb1, priv, "private_data");
565
566 /* fake succesfull connection */
567 will_return(__wrap_connect, 0);
568 will_return(__wrap_ssh_connect, 0);
569 /* do not authenticate using no authentication method */
570 will_return(__wrap_ssh_userauth_none, 1);
571
572 /* succesfully authenticate via password authentication */
573 expect_string(__wrap_ssh_userauth_password, password, "secret password");
574 expect_string(__wrap_ssh_userauth_password, username, "username");
575 will_return(__wrap_ssh_userauth_password, 0);
576
577 /* fake ssh functions that are used to open netconf channel */
578 will_return(__wrap_ssh_channel_open_session, 0);
579 will_return(__wrap_ssh_channel_request_subsystem, 0);
580
581 /* fake that connection is still alive*/
582 will_return(__wrap_ssh_is_connected, 1);
583
584 /* fake ssh function for recieving hello message */
585 will_return(__wrap_ssh_is_connected, 1);
586
587 will_return(__wrap_nc_handshake_io, 3);
588 will_return(__wrap_nc_ctx_check_and_fill, 0);
589
590 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
591 assert_non_null(session);
592
593 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200594 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200595 nc_session_free(session, NULL);
596}
597
598static void
David Sedlák77acc202018-10-08 21:44:14 +0200599test_nc_connect_ssh_pubkey_succesfull(void **state)
600{
601 (void)state;
602 struct nc_session *session;
603 int ret = 0;
604
605 /* set authentication method to use password authentication */
606 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
607 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
608 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
609
610 /* add keypair for authentication */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200611 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_ecdsa.pub", TESTS_DIR "/data/key_ecdsa");
David Sedlák77acc202018-10-08 21:44:14 +0200612 assert_int_equal(ret, 0);
613
614 /* fake succesfull connection */
615 will_return(__wrap_connect, 0);
616 will_return(__wrap_ssh_connect, 0);
617 /* do not authenticate using no authentication method */
618 will_return(__wrap_ssh_userauth_none, 1);
619 will_return(__wrap_ssh_userauth_try_publickey, 0);
620 will_return(__wrap_ssh_userauth_publickey, 0);
621 will_return(__wrap_ssh_is_connected, 1);
622 will_return(__wrap_ssh_channel_open_session, 0);
623 will_return(__wrap_ssh_channel_request_subsystem, 0);
624
625 /* fake ssh function for recieving hello message */
626 will_return(__wrap_ssh_is_connected, 1);
627
628 will_return(__wrap_nc_handshake_io, 3);
629 will_return(__wrap_nc_ctx_check_and_fill, 0);
630 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
631 assert_non_null(session);
632
633 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200634 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlák77acc202018-10-08 21:44:14 +0200635 nc_session_free(session, NULL);
636}
637
638static void
David Sedlákddde4492018-09-30 21:34:38 +0200639test_nc_connect_connection_failed(void **state)
640{
641 (void)state;
642 struct nc_session *session;
643
644 errno = ECONNREFUSED;
645 will_return(__wrap_connect, -1);
646 will_return(__wrap_ssh_is_connected, 0);
647
648 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
649 assert_null(session);
650}
651
652static void
653test_nc_connect_ssh_bad_hello(void **state)
654{
655 (void)state;
656 struct nc_session *session;
657
658 /* set authentication method to use interactive authentication */
659 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
660 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
661 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
662
663 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, NULL);
664
665 will_return(__wrap_connect, 0);
666 will_return(__wrap_ssh_connect, 0);
667 will_return(__wrap_ssh_userauth_none, 1);
668
669 will_return(__wrap_ssh_userauth_kbdint, 0);
670 will_return(__wrap_ssh_is_connected, 1);
671 will_return(__wrap_ssh_is_connected, 1);
672
673 will_return(__wrap_ssh_channel_open_session, 0);
674 will_return(__wrap_ssh_channel_request_subsystem, 0);
675 will_return(__wrap_nc_handshake_io, 4);
676
677 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
678 assert_null(session);
679
David Sedlákaae4df32018-10-08 22:27:22 +0200680 /* destroy client, must be called in last test */
David Sedlákddde4492018-09-30 21:34:38 +0200681 nc_client_destroy();
682}
683
Fred Gan3a736e02021-01-04 17:59:38 +0800684static void
685test_nc_client_ssh_ch_setting_username(void **state)
686{
687 (void)state;
688 const char *username_ret;
689 int ret;
690
691 /* username is set to "ch_username" in setup_f */
692 username_ret = nc_client_ssh_ch_get_username();
693 assert_string_equal(username_ret, "ch_username");
694 /* set new username and check if it changes */
695 ret = nc_client_ssh_ch_set_username("new_ch_username");
696 assert_int_equal(ret, 0);
697 username_ret = nc_client_ssh_ch_get_username();
698 assert_string_equal(username_ret, "new_ch_username");
699}
700
701static void
702test_nc_client_ssh_ch_add_bind_listen(void **state)
703{
704 (void)state;
705 int ret;
706
707 /* invalid parameters, address NULL or port 0 */
708 ret = nc_client_ssh_ch_add_bind_listen(NULL, 4334);
709 assert_int_equal(ret, -1);
710 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 0);
711 assert_int_equal(ret, -1);
712
713 /* failed to create an ssh listening socket */
714 will_return(__wrap_nc_sock_listen_inet, -1);
715 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
716 assert_int_equal(ret, -1);
717
718 /* fake a successful CH ssh listening socket */
719 will_return(__wrap_nc_sock_listen_inet, 1);
720 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
721 assert_int_equal(ret, 0);
722
723 /* remove ssh listening client binds */
724 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
725 assert_int_equal(ret, 0);
726}
727
728static void
729test_nc_accept_callhome(void **state)
730{
731 (void)state;
732 struct nc_session *session = NULL;
733 int timeout = 10;
734 int ret;
735
736 /* invalid parameter session */
737 ret = nc_accept_callhome(timeout, NULL, NULL);
738 assert_int_equal(ret, -1);
739
740 /* no client bind */
741 ret = nc_accept_callhome(timeout, NULL, &session);
742 assert_int_equal(ret, -1);
743
744 /* successfully add a client Call Home bind */
745 will_return(__wrap_nc_sock_listen_inet, 1);
746 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
747 assert_int_equal(ret, 0);
748
749 /* failed to accept a client bind */
750 will_return(__wrap_nc_sock_accept_binds, -1);
751 ret = nc_accept_callhome(timeout, NULL, &session);
752 assert_int_equal(ret, -1);
753
754 /* failed to accept a server Call Home connection */
755 will_return(__wrap_nc_accept_callhome_ssh_sock, NULL);
756 will_return(__wrap_nc_sock_accept_binds, 2);
757 ret = nc_accept_callhome(timeout, NULL, &session);
758 assert_int_equal(ret, -1);
759
760 /* create session structure to fake a successful server call home connection */
761 session = nc_new_session(NC_CLIENT, 0);
762 assert_non_null(session);
763 will_return(__wrap_nc_sock_accept_binds, 2);
764 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
765 ret = nc_accept_callhome(timeout, NULL, &session);
766 assert_int_equal(ret, 1);
767
768 /* remove ssh listening client binds */
769 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
770 assert_int_equal(ret, 0);
771
772 /* free session */
773 nc_session_free(session, NULL);
774}
775
776static void
777test_nc_client_ssh_callhome_successful(void **state)
778{
779 (void)state;
780 struct nc_session *session = NULL;
781 int timeout = 10;
782 int ret;
783
784 /* create session structure */
785 session = nc_new_session(NC_CLIENT, 0);
786 assert_non_null(session);
787
788 /* prepare to fake return values for functions used by nc_accept_callhome */
789 will_return(__wrap_nc_sock_listen_inet, 1);
790 will_return(__wrap_nc_sock_accept_binds, 2);
791 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
792
793 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
794 assert_int_equal(ret, 0);
795 ret = nc_accept_callhome(timeout, NULL, &session);
796 assert_int_equal(ret, 1);
797
798 /* remove ssh listening client binds */
799 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
800 assert_int_equal(ret, 0);
801
802 /* free session */
803 nc_session_free(session, NULL);
804}
805
David Sedlákddde4492018-09-30 21:34:38 +0200806int
807main(void)
808{
809 const struct CMUnitTest tests[] = {
810 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_pref, setup_f, teardown_f),
811 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_hostkey_check_clb, setup_f, teardown_f),
812 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_password_clb, setup_f, teardown_f),
813 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_interactive_clb, setup_f, teardown_f),
814 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_privkey_passphrase_clb, setup_f, teardown_f),
815 cmocka_unit_test_setup_teardown(test_nc_client_ssh_adding_keypair, setup_f, teardown_f),
816 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_username, setup_f, teardown_f),
817 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_interactive_succesfull, setup_f, teardown_f),
818 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_password_succesfull, setup_f, teardown_f),
David Sedlák77acc202018-10-08 21:44:14 +0200819 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_succesfull, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200820 cmocka_unit_test_setup_teardown(test_nc_connect_connection_failed, setup_f, teardown_f),
821 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_bad_hello, setup_f, teardown_f),
Fred Gan3a736e02021-01-04 17:59:38 +0800822 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_setting_username, setup_f, teardown_f),
823 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_add_bind_listen, setup_f, teardown_f),
824 cmocka_unit_test_setup_teardown(test_nc_accept_callhome, setup_f, teardown_f),
825 cmocka_unit_test_setup_teardown(test_nc_client_ssh_callhome_successful, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200826 };
827
828 return cmocka_run_group_tests(tests, NULL, NULL);
829}