blob: 571b844d6d08b03392dcd394331c1f471486174a [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
David Sedlákddde4492018-09-30 21:34:38 +020038setup_f(void **state)
39{
40 (void)state;
41 int ret;
42
43 nc_verbosity(NC_VERB_VERBOSE);
44
roman899a91f2023-10-26 14:51:44 +020045 /* init client */
46 nc_client_init();
47
David Sedlákddde4492018-09-30 21:34:38 +020048 ret = nc_client_ssh_set_username("username");
49 assert_int_equal(ret, 0);
Fred Gan3a736e02021-01-04 17:59:38 +080050 ret = nc_client_ssh_ch_set_username("ch_username");
51 assert_int_equal(ret, 0);
roman899a91f2023-10-26 14:51:44 +020052 /* skip all hostkey and known_hosts checks */
53 nc_client_ssh_set_knownhosts_mode(NC_SSH_KNOWNHOSTS_SKIP);
David Sedlákddde4492018-09-30 21:34:38 +020054
55 return 0;
56}
57
58static int
59teardown_f(void **state)
60{
61 (void)state;
roman899a91f2023-10-26 14:51:44 +020062 /* destroy client */
roman33ef8712023-02-17 10:25:12 +010063 nc_client_destroy();
David Sedlákddde4492018-09-30 21:34:38 +020064 return 0;
65}
66
67MOCK int
68__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
69{
70 (void)sockfd;
71 (void)addr;
72 (void)addrlen;
73
74 return (int)mock();
75}
76
77MOCK int
78__wrap_ssh_connect(ssh_session session)
79{
80 (void)session;
81
82 /* set support of all authentication methods by fake server */
83 ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
84 return (int)mock();
85}
86
87MOCK int
88__wrap_ssh_userauth_none(ssh_session session, const char *username)
89{
90 (void)session;
91 (void)username;
92
93 return (int)mock();
94}
95
96MOCK int
97__wrap_ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods)
98{
99 (void)session;
100 (void)user;
101 (void)submethods;
102
103 return (int)mock();
104}
105
106MOCK int
107__wrap_ssh_is_connected(ssh_session session)
108{
109 (void)session;
110
111 return (int)mock();
112}
113
114MOCK int
115__wrap_ssh_channel_open_session(ssh_channel channel)
116{
117 (void)channel;
118
119 return (int)mock();
120}
121
122MOCK int
123__wrap_ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem)
124{
125 (void)channel;
126 (void)subsystem;
127
128 return (int)mock();
129}
130
131MOCK int
132__wrap_ssh_channel_is_closed(ssh_channel channel)
133{
134 (void)channel;
135
136 return 0;
137}
138
139MOCK int
140__wrap_ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
141{
142 (void)channel;
143 (void)data;
144
145 return len;
146}
147
148MOCK int
149__wrap_ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
150{
151 (void)channel;
152 (void)timeout;
153 (void)is_stderr;
154
155 return (int)mock();
156}
157
158MOCK int
159__wrap_ssh_userauth_password(ssh_session session, const char *username, const char *password)
160{
161 (void)session;
162 check_expected(password);
163 check_expected(username);
164
David Sedlákddde4492018-09-30 21:34:38 +0200165 return (int)mock();
166}
167
168MOCK int
169__wrap_nc_handshake_io(struct nc_session *session)
170{
171 (void)session;
172
173 return (int)mock();
174}
175
176MOCK int
177__wrap_nc_ctx_check_and_fill(struct nc_session *session)
178{
179 (void)session;
180
181 return (int)mock();
182}
183
David Sedlák77acc202018-10-08 21:44:14 +0200184MOCK int
185__wrap_ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey)
186{
187 (void)session;
188 (void)username;
189 (void)pubkey;
190
191 return (int)mock();
192}
193
194MOCK int
195__wrap_ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey)
196{
197 (void)session;
198 (void)username;
199 (void)privkey;
200
201 return (int)mock();
202}
203
Fred Gan3a736e02021-01-04 17:59:38 +0800204MOCK int
205__wrap_nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
206{
207 (void)address;
208 (void)port;
209 (void)ka;
210
211 return (int)mock();
212}
213
214MOCK int
roman899a91f2023-10-26 14:51:44 +0200215__wrap_nc_sock_accept_binds(struct nc_bind *binds, uint16_t bind_count, pthread_mutex_t *bind_lock, int timeout, char **host, uint16_t *port, uint16_t *idx)
Fred Gan3a736e02021-01-04 17:59:38 +0800216{
217 (void)binds;
218 (void)bind_count;
roman899a91f2023-10-26 14:51:44 +0200219 (void)bind_lock;
Fred Gan3a736e02021-01-04 17:59:38 +0800220 (void)timeout;
221 (void)host;
222 (void)port;
223
224 *idx = 0;
225 return (int)mock();
226}
227
228MOCK struct nc_session *
229__wrap_nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout)
230{
231 (void)sock;
232 (void)host;
233 (void)port;
234 (void)ctx;
235 (void)timeout;
236
237 return mock_ptr_type(struct nc_session *);
238}
239
David Sedlákddde4492018-09-30 21:34:38 +0200240char *
241test_pwd_clb1(const char *username, const char *hostname, void *priv)
242{
243 char *pass, *pass_to_return;
244
245 check_expected(username);
246 check_expected(hostname);
247 check_expected(priv);
248
249 pass = (char *)mock();
250 pass_to_return = malloc(sizeof *pass * (strlen(pass) + 1));
251 strcpy(pass_to_return, pass);
252
253 return pass_to_return;
254}
255
256char *
257test_pwd_clb2(const char *username, const char *hostname, void *priv)
258{
259 (void)username;
260 (void)hostname;
261 (void)priv;
262
263 return 0;
264}
265
266static void
267test_nc_client_ssh_setting_auth_password_clb(void **state)
268{
269 (void)state;
270 char *(*ret_f)(const char *username, const char *hostname, void *priv);
271 char *priv_data_ret;
272
273 /* set callback */
274 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "DATA");
275 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
276 assert_ptr_equal(test_pwd_clb1, ret_f);
277 assert_string_equal("DATA", priv_data_ret);
278
279 /* set different callback */
280 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, "NEW DATA");
281 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
282 assert_ptr_equal(test_pwd_clb2, ret_f);
283 assert_string_equal("NEW DATA", priv_data_ret);
284}
285
286char *
287test_inter_clb1(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
288{
289 (void)auth_name;
290 (void)instruction;
291 (void)prompt;
292 (void)echo;
293 (void)priv;
294
295 return 0;
296}
297
298char *
299test_inter_clb2(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
300{
301 (void)auth_name;
302 (void)instruction;
303 (void)prompt;
304 (void)echo;
305 (void)priv;
306
307 return 0;
308}
309
310static void
311test_nc_client_ssh_setting_auth_interactive_clb(void **state)
312{
313 (void)state;
314 char *(*ret_f)(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv);
315 char *priv_data_ret;
316
317 /* set callback */
318 nc_client_ssh_set_auth_interactive_clb(test_inter_clb1, "DATA");
319 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
320 assert_ptr_equal(test_inter_clb1, ret_f);
321 assert_string_equal("DATA", priv_data_ret);
322
323 /* set diferent callback */
324 nc_client_ssh_set_auth_interactive_clb(test_inter_clb2, "NEW DATA");
325 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
326 assert_ptr_equal(test_inter_clb2, ret_f);
327 assert_string_equal("NEW DATA", priv_data_ret);
328}
329
330char *
331test_passphrase_clb1(const char *privkey_path, void *priv)
332{
333 (void)privkey_path;
334 (void)priv;
335
336 return 0;
337}
338
339char *
340test_passphrase_clb2(const char *privkey_path, void *priv)
341{
342 (void)privkey_path;
343 (void)priv;
344
345 return 0;
346}
347
348static void
349test_nc_client_ssh_setting_auth_privkey_passphrase_clb(void **state)
350{
351 (void)state;
352 char *(*ret_f)(const char *privkey_path, void *priv);
353 char *priv_data_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200354
David Sedlákddde4492018-09-30 21:34:38 +0200355 /* set first callback */
356 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb1, "DATA");
357 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
358 assert_ptr_equal(ret_f, test_passphrase_clb1);
359 assert_string_equal("DATA", priv_data_ret);
360
361 /* set different callback */
362 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb2, "NEW DATA");
363 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
364 assert_ptr_equal(ret_f, test_passphrase_clb2);
365 assert_string_equal("NEW DATA", priv_data_ret);
366}
367
368static void
369test_nc_client_ssh_adding_keypair(void **state)
370{
371 (void)state;
372 int ret;
Michal Vaskoe2bfcd62024-03-28 07:58:49 +0100373 const char *pubkey1 = NULL, *pubkey2 = NULL;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200374
David Sedlákddde4492018-09-30 21:34:38 +0200375 /* at the beginning keypair count should be 0 */
376 ret = nc_client_ssh_get_keypair_count();
377 assert_int_equal(ret, 0);
378
379 /* add first key pair */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200380 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 +0200381 assert_int_equal(ret, 0);
382 ret = nc_client_ssh_get_keypair_count();
383 assert_int_equal(ret, 1);
384
385 /* add second keypair */
Michal Vaskoacd4ba82024-02-02 14:11:13 +0100386 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_rsa.pub", TESTS_DIR "/data/key_rsa");
David Sedlákddde4492018-09-30 21:34:38 +0200387 assert_int_equal(ret, 0);
388 ret = nc_client_ssh_get_keypair_count();
389 assert_int_equal(ret, 2);
390 ret = nc_client_ssh_get_keypair(1, &pubkey1, &pubkey2);
391 assert_int_equal(ret, 0);
Michal Vaskoacd4ba82024-02-02 14:11:13 +0100392 assert_string_equal(pubkey1, TESTS_DIR "/data/key_rsa.pub");
393 assert_string_equal(pubkey2, TESTS_DIR "/data/key_rsa");
David Sedlákddde4492018-09-30 21:34:38 +0200394
395 /* delete first keypair */
396 ret = nc_client_ssh_del_keypair(0);
397 assert_int_equal(ret, 0);
398 ret = nc_client_ssh_get_keypair_count();
399 assert_int_equal(ret, 1);
400 /* try to get deleted keypair */
401 ret = nc_client_ssh_get_keypair(5, &pubkey1, &pubkey2);
402 assert_int_equal(ret, -1);
403
404 /* try to add keypair that is already set */
Michal Vaskoacd4ba82024-02-02 14:11:13 +0100405 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_rsa.pub", TESTS_DIR "/data/key_rsa");
David Sedlákddde4492018-09-30 21:34:38 +0200406 assert_int_equal(ret, -1);
407 ret = nc_client_ssh_get_keypair_count();
408 assert_int_equal(ret, 1);
409
410 /* try to delete keypair with id that is not used */
411 ret = nc_client_ssh_del_keypair(42);
412 assert_int_equal(ret, -1);
413 ret = nc_client_ssh_get_keypair_count();
414 assert_int_equal(ret, 1);
415
416 /* remove remaining keypairs */
417 ret = nc_client_ssh_del_keypair(0);
418 assert_int_equal(ret, 0);
419 ret = nc_client_ssh_get_keypair_count();
420 assert_int_equal(ret, 0);
421}
422
423static void
424test_nc_client_ssh_setting_auth_pref(void **state)
425{
426 (void)state;
427 int ret;
428
David Sedlákddde4492018-09-30 21:34:38 +0200429 /* check default prefference settings according to documentation */
430 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
roman41a11e42022-06-22 09:27:08 +0200431 assert_int_equal(ret, 1);
David Sedlákddde4492018-09-30 21:34:38 +0200432 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
433 assert_int_equal(ret, 2);
434 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
roman41a11e42022-06-22 09:27:08 +0200435 assert_int_equal(ret, 3);
David Sedlákddde4492018-09-30 21:34:38 +0200436
437 /* try to set prefetence of non existing method */
438 nc_client_ssh_set_auth_pref(42, 22);
439
440 /* try to get preference of non existing method */
441 ret = nc_client_ssh_get_auth_pref(42);
442 assert_int_equal(ret, 0);
443
444 /* change values of all methods and check if they actually changed */
445 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 9);
446 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
447 assert_int_equal(ret, 9);
448
449 /* negative value should be set as -1 */
450 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -5);
451 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
452 assert_int_equal(ret, -1);
453
454 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 11);
455 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
456 assert_int_equal(ret, 11);
457}
458
459static void
460test_nc_client_ssh_setting_username(void **state)
461{
462 (void)state;
463 int ret;
464 const char *username_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200465
David Sedlákddde4492018-09-30 21:34:38 +0200466 username_ret = nc_client_ssh_get_username();
467 /* username is set to "username" in setup_f */
468 assert_string_equal(username_ret, "username");
469
470 /* set new username and check if it changes */
471 ret = nc_client_ssh_set_username("new_username");
472 assert_int_equal(ret, 0);
473 username_ret = nc_client_ssh_get_username();
474 assert_string_equal(username_ret, "new_username");
475}
476
477static void
478test_nc_connect_ssh_interactive_succesfull(void **state)
479{
480 (void)state;
481 struct nc_session *session;
482
483 /* set authentication method to use interactive authentication */
484 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
485 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
486 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
487
488 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 20);
489
490 /* prepare return values for functions used by nc_connect_ssh */
491 will_return(__wrap_connect, 0);
492 will_return(__wrap_ssh_connect, 0);
493 will_return(__wrap_ssh_userauth_none, 1);
494
495 will_return(__wrap_ssh_userauth_kbdint, 0);
496 will_return(__wrap_ssh_is_connected, 1);
497 will_return(__wrap_ssh_is_connected, 1);
498
499 will_return(__wrap_ssh_channel_open_session, 0);
500 will_return(__wrap_ssh_channel_request_subsystem, 0);
501
502 will_return(__wrap_nc_handshake_io, 3);
503 will_return(__wrap_nc_ctx_check_and_fill, 0);
504
505 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
506 assert_non_null(session);
507
Michal Vasko0ab3a662021-07-26 12:17:41 +0200508 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200509 nc_session_free(session, NULL);
510}
511
512static void
513test_nc_connect_ssh_password_succesfull(void **state)
514{
515 (void)state;
516 struct nc_session *session;
517
518 /* set authentication method to use password authentication */
519 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 1);
520 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
521 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
522
523 /* set authentication callback */
524 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "private_data");
525 will_return(test_pwd_clb1, "secret password");
526 /* set values that are expected as parameters for authentication callback */
527 expect_string(test_pwd_clb1, username, "username");
528 expect_string(test_pwd_clb1, hostname, "127.0.0.1");
529 expect_string(test_pwd_clb1, priv, "private_data");
530
531 /* fake succesfull connection */
532 will_return(__wrap_connect, 0);
533 will_return(__wrap_ssh_connect, 0);
534 /* do not authenticate using no authentication method */
535 will_return(__wrap_ssh_userauth_none, 1);
536
537 /* succesfully authenticate via password authentication */
538 expect_string(__wrap_ssh_userauth_password, password, "secret password");
539 expect_string(__wrap_ssh_userauth_password, username, "username");
540 will_return(__wrap_ssh_userauth_password, 0);
541
542 /* fake ssh functions that are used to open netconf channel */
543 will_return(__wrap_ssh_channel_open_session, 0);
544 will_return(__wrap_ssh_channel_request_subsystem, 0);
545
546 /* fake that connection is still alive*/
547 will_return(__wrap_ssh_is_connected, 1);
548
549 /* fake ssh function for recieving hello message */
550 will_return(__wrap_ssh_is_connected, 1);
551
552 will_return(__wrap_nc_handshake_io, 3);
553 will_return(__wrap_nc_ctx_check_and_fill, 0);
554
555 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
556 assert_non_null(session);
557
558 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200559 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200560 nc_session_free(session, NULL);
561}
562
563static void
roman899a91f2023-10-26 14:51:44 +0200564test_nc_connect_ssh_pubkey_succesfull(void **state)
David Sedlák77acc202018-10-08 21:44:14 +0200565{
566 (void)state;
567 struct nc_session *session;
568 int ret = 0;
569
570 /* set authentication method to use password authentication */
571 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
572 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
573 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
574
575 /* add keypair for authentication */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200576 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 +0200577 assert_int_equal(ret, 0);
578
579 /* fake succesfull connection */
580 will_return(__wrap_connect, 0);
581 will_return(__wrap_ssh_connect, 0);
582 /* do not authenticate using no authentication method */
583 will_return(__wrap_ssh_userauth_none, 1);
584 will_return(__wrap_ssh_userauth_try_publickey, 0);
585 will_return(__wrap_ssh_userauth_publickey, 0);
586 will_return(__wrap_ssh_is_connected, 1);
587 will_return(__wrap_ssh_channel_open_session, 0);
588 will_return(__wrap_ssh_channel_request_subsystem, 0);
589
590 /* fake ssh function for recieving hello message */
591 will_return(__wrap_ssh_is_connected, 1);
592
593 will_return(__wrap_nc_handshake_io, 3);
594 will_return(__wrap_nc_ctx_check_and_fill, 0);
595 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
596 assert_non_null(session);
597
598 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200599 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlák77acc202018-10-08 21:44:14 +0200600 nc_session_free(session, NULL);
601}
602
603static void
David Sedlákddde4492018-09-30 21:34:38 +0200604test_nc_connect_connection_failed(void **state)
605{
606 (void)state;
607 struct nc_session *session;
608
609 errno = ECONNREFUSED;
610 will_return(__wrap_connect, -1);
611 will_return(__wrap_ssh_is_connected, 0);
612
613 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
614 assert_null(session);
615}
616
617static void
618test_nc_connect_ssh_bad_hello(void **state)
619{
620 (void)state;
621 struct nc_session *session;
622
623 /* set authentication method to use interactive authentication */
624 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
625 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
626 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
627
628 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, NULL);
629
630 will_return(__wrap_connect, 0);
631 will_return(__wrap_ssh_connect, 0);
632 will_return(__wrap_ssh_userauth_none, 1);
633
634 will_return(__wrap_ssh_userauth_kbdint, 0);
635 will_return(__wrap_ssh_is_connected, 1);
636 will_return(__wrap_ssh_is_connected, 1);
637
638 will_return(__wrap_ssh_channel_open_session, 0);
639 will_return(__wrap_ssh_channel_request_subsystem, 0);
640 will_return(__wrap_nc_handshake_io, 4);
641
642 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
643 assert_null(session);
David Sedlákddde4492018-09-30 21:34:38 +0200644}
645
Fred Gan3a736e02021-01-04 17:59:38 +0800646static void
647test_nc_client_ssh_ch_setting_username(void **state)
648{
649 (void)state;
650 const char *username_ret;
651 int ret;
652
653 /* username is set to "ch_username" in setup_f */
654 username_ret = nc_client_ssh_ch_get_username();
655 assert_string_equal(username_ret, "ch_username");
656 /* set new username and check if it changes */
657 ret = nc_client_ssh_ch_set_username("new_ch_username");
658 assert_int_equal(ret, 0);
659 username_ret = nc_client_ssh_ch_get_username();
660 assert_string_equal(username_ret, "new_ch_username");
661}
662
663static void
664test_nc_client_ssh_ch_add_bind_listen(void **state)
665{
666 (void)state;
667 int ret;
668
669 /* invalid parameters, address NULL or port 0 */
670 ret = nc_client_ssh_ch_add_bind_listen(NULL, 4334);
671 assert_int_equal(ret, -1);
672 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 0);
673 assert_int_equal(ret, -1);
674
675 /* failed to create an ssh listening socket */
676 will_return(__wrap_nc_sock_listen_inet, -1);
677 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
678 assert_int_equal(ret, -1);
679
680 /* fake a successful CH ssh listening socket */
roman899a91f2023-10-26 14:51:44 +0200681 will_return(__wrap_nc_sock_listen_inet, 5);
Fred Gan3a736e02021-01-04 17:59:38 +0800682 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
683 assert_int_equal(ret, 0);
684
685 /* remove ssh listening client binds */
686 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
687 assert_int_equal(ret, 0);
688}
689
690static void
691test_nc_accept_callhome(void **state)
692{
693 (void)state;
694 struct nc_session *session = NULL;
695 int timeout = 10;
696 int ret;
697
698 /* invalid parameter session */
699 ret = nc_accept_callhome(timeout, NULL, NULL);
700 assert_int_equal(ret, -1);
701
702 /* no client bind */
703 ret = nc_accept_callhome(timeout, NULL, &session);
704 assert_int_equal(ret, -1);
705
706 /* successfully add a client Call Home bind */
707 will_return(__wrap_nc_sock_listen_inet, 1);
708 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
709 assert_int_equal(ret, 0);
710
711 /* failed to accept a client bind */
712 will_return(__wrap_nc_sock_accept_binds, -1);
713 ret = nc_accept_callhome(timeout, NULL, &session);
714 assert_int_equal(ret, -1);
715
716 /* failed to accept a server Call Home connection */
717 will_return(__wrap_nc_accept_callhome_ssh_sock, NULL);
718 will_return(__wrap_nc_sock_accept_binds, 2);
719 ret = nc_accept_callhome(timeout, NULL, &session);
720 assert_int_equal(ret, -1);
721
722 /* create session structure to fake a successful server call home connection */
723 session = nc_new_session(NC_CLIENT, 0);
724 assert_non_null(session);
725 will_return(__wrap_nc_sock_accept_binds, 2);
726 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
727 ret = nc_accept_callhome(timeout, NULL, &session);
728 assert_int_equal(ret, 1);
729
730 /* remove ssh listening client binds */
731 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
732 assert_int_equal(ret, 0);
733
734 /* free session */
735 nc_session_free(session, NULL);
736}
737
738static void
739test_nc_client_ssh_callhome_successful(void **state)
740{
741 (void)state;
742 struct nc_session *session = NULL;
743 int timeout = 10;
744 int ret;
745
746 /* create session structure */
747 session = nc_new_session(NC_CLIENT, 0);
748 assert_non_null(session);
749
750 /* prepare to fake return values for functions used by nc_accept_callhome */
751 will_return(__wrap_nc_sock_listen_inet, 1);
752 will_return(__wrap_nc_sock_accept_binds, 2);
753 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
754
755 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
756 assert_int_equal(ret, 0);
757 ret = nc_accept_callhome(timeout, NULL, &session);
758 assert_int_equal(ret, 1);
759
760 /* remove ssh listening client binds */
761 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
762 assert_int_equal(ret, 0);
763
764 /* free session */
765 nc_session_free(session, NULL);
766}
767
David Sedlákddde4492018-09-30 21:34:38 +0200768int
769main(void)
770{
771 const struct CMUnitTest tests[] = {
772 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_pref, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200773 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_password_clb, setup_f, teardown_f),
774 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_interactive_clb, setup_f, teardown_f),
775 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_privkey_passphrase_clb, setup_f, teardown_f),
776 cmocka_unit_test_setup_teardown(test_nc_client_ssh_adding_keypair, setup_f, teardown_f),
777 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_username, setup_f, teardown_f),
778 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_interactive_succesfull, setup_f, teardown_f),
779 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_password_succesfull, setup_f, teardown_f),
David Sedlák77acc202018-10-08 21:44:14 +0200780 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_succesfull, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200781 cmocka_unit_test_setup_teardown(test_nc_connect_connection_failed, setup_f, teardown_f),
782 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_bad_hello, setup_f, teardown_f),
Fred Gan3a736e02021-01-04 17:59:38 +0800783 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_setting_username, setup_f, teardown_f),
784 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_add_bind_listen, setup_f, teardown_f),
785 cmocka_unit_test_setup_teardown(test_nc_accept_callhome, setup_f, teardown_f),
786 cmocka_unit_test_setup_teardown(test_nc_client_ssh_callhome_successful, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200787 };
788
789 return cmocka_run_group_tests(tests, NULL, NULL);
790}