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