blob: 20c546b1a9856341a5b4e55fc0206994e16ac88d [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>
romanc1d2b092023-02-02 08:58:27 +010026#include <config_server.h>
David Sedlákddde4492018-09-30 21:34:38 +020027#include <libyang/libyang.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020028#include <log.h>
David Sedlákddde4492018-09-30 21:34:38 +020029#include <session_client.h>
Fred Gan3a736e02021-01-04 17:59:38 +080030#include <session_client_ch.h>
31#include <session_p.h>
roman33ef8712023-02-17 10:25:12 +010032#include <session_server.h>
David Sedlákddde4492018-09-30 21:34:38 +020033#include "tests/config.h"
34
David Sedlákddde4492018-09-30 21:34:38 +020035#include <libssh/callbacks.h>
Michal Vaskob83a3fa2021-05-26 09:53:42 +020036#include <libssh/libssh.h>
David Sedlákddde4492018-09-30 21:34:38 +020037#include <libssh/server.h>
38
romanc1d2b092023-02-02 08:58:27 +010039const char *data =
40 "<netconf-server xmlns=\"urn:ietf:params:xml:ns:yang:ietf-netconf-server\" xmlns:yang=\"urn:ietf:params:xml:ns:yang:1\" yang:operation=\"none\">\n"
41 " <listen yang:operation=\"create\">\n"
42 " <idle-timeout>10</idle-timeout>\n"
43 " <endpoint>\n"
44 " <name>default-ssh</name>\n"
45 " <ssh>\n"
46 " <tcp-server-parameters>\n"
47 " <local-address>127.0.0.1</local-address>\n"
48 " <local-port>10005</local-port>\n"
49 " </tcp-server-parameters>\n"
50 " <ssh-server-parameters>\n"
51 " <server-identity>\n"
52 " <host-key>\n"
53 " <name>key</name>\n"
54 " <public-key>\n"
55 " <local-definition>\n"
56 " <public-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:ssh-public-key-format</public-key-format>\n"
57 " <public-key>MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA6ojtjfDmvyQP1ZkIwBpr97eKDuebvpoglRHRdvVuTpf/gU1VArAQmwGh05i6lm8TkVl1noMlIxLJDcWslaeVn6KyvsX0HhsQtXwqPqwka5UCv6alwf/ivAvcNpcX1j0t/uIGCI4dSiKnzQCyf0FTirzQkjrDZUd3meDhNQTruCalGV4gfNWIq3e1oGuwAn1tLlu9oTrE4HzMpgbNEU6wNmsSqpwGxUhYLoSaM7b0dLmqP+ZczSS0Uac0PFNkehGQ2CYIT80f580o4XGtoLCUUGkp6YCTL4Z2CeBEaJABWjDIDH+dKYIUBqUpz4Th12gXAP+h+3qI6+9eppeHrfrzARDsfLjwUNxQJse1QSArjAytf0FKtGHrORc7W0TiCFvR0zaoUNLTKk7enTiRQ9rfWZOAu44fUvPCaXDE6zXXeaVgoKCo4VHlho36erUcjlEBM+jk28IykbZGtBb6igKvYa1tPSgeYm/zJoFVjQcnr14uci/ft1+Na+hOIEoEEiKxcAPk2b2vBKNlRIW7WLJ3u7ZiuQEJTNm6+3cE4+lfwaBCBqBToE+dpzvoUXoMyFFReUFd1O5axu4fXgt00jMaOQxmE0v9OmR/pL/PWIflVF4Zz5yVONYaDVc7l+veY0oEZruEPJ0hlEgxuCzLrcMhjufl2qE2Q7fQIaav/1NqBVkCAwEAAQ==</public-key>\n"
58 " <private-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:rsa-private-key-format</private-key-format>\n"
59 " <cleartext-private-key>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</cleartext-private-key>\n"
60 " </local-definition>\n"
61 " </public-key>\n"
62 " </host-key>\n"
63 " </server-identity>\n"
64 " <client-authentication>\n"
65 " <users>\n"
66 " <user>\n"
67 " <name>test</name>\n"
68 " <public-keys>\n"
69 " <local-definition>\n"
70 " <public-key>\n"
71 " <name>client</name>\n"
72 " <public-key-format xmlns:ct=\"urn:ietf:params:xml:ns:yang:ietf-crypto-types\">ct:ssh-public-key-format</public-key-format>\n"
73 " <public-key>AAAAB3NzaC1yc2EAAAADAQABAAABAQDPavVALiM7QwTIUAndO8E9GOkSDQWjuEwkzbJ3kOBPa7kkq71UOZFeecDjFb9eipkljfFys/JYHGQaYVF8/svT0KV5h7HlutRdF6yvqSEbjpbTORb27pdHX3iFEyDCwCIoq9vMeX+wyXnteyn01GpIL0ig0WAnvkqX/SPjuplX5ZItUSr0MhXM7fNSX50BD6G8IO0/djUcdMUcjTjGv73SxB9ZzLvxnhXuUJbzEJJJLj6qajyEIVaJSa73vA33JCD8qzarrsuITojVLPDFmeHwSAoB5dP86yop6e6ypuXzKxxef6yNXcE8oTj8UFYBIXsgIP2nBvWk41EaK0Vk3YFl</public-key>\n"
74 " </public-key>\n"
75 " </local-definition>\n"
76 " </public-keys>\n"
77 " </user>\n"
78 " </users>\n"
79 " </client-authentication>\n"
80 " <transport-params>\n"
81 " <host-key>\n"
82 " <host-key-alg xmlns:sshpka=\"urn:ietf:params:xml:ns:yang:iana-ssh-public-key-algs\">sshpka:rsa-sha2-512</host-key-alg>\n"
83 " </host-key>\n"
84 " <key-exchange>\n"
85 " <key-exchange-alg xmlns:sshkea=\"urn:ietf:params:xml:ns:yang:iana-ssh-key-exchange-algs\">sshkea:curve25519-sha256</key-exchange-alg>\n"
86 " </key-exchange>\n"
87 " <encryption>\n"
88 " <encryption-alg xmlns:sshea=\"urn:ietf:params:xml:ns:yang:iana-ssh-encryption-algs\">sshea:aes256-ctr</encryption-alg>\n"
89 " </encryption>\n"
90 " <mac>\n"
91 " <mac-alg xmlns:sshma=\"urn:ietf:params:xml:ns:yang:iana-ssh-mac-algs\">sshma:hmac-sha2-512</mac-alg>\n"
92 " </mac>\n"
93 " </transport-params>\n"
94 " </ssh-server-parameters>\n"
95 " </ssh>\n"
96 " </endpoint>\n"
97 " </listen>\n"
98 "</netconf-server>\n";
99
David Sedlákddde4492018-09-30 21:34:38 +0200100static int
101ssh_hostkey_check_clb(const char *hostname, ssh_session session, void *priv)
102{
103 (void)hostname;
104 (void)session;
105 (void)priv;
106
107 return 0;
108}
109
110static int
111setup_f(void **state)
112{
113 (void)state;
114 int ret;
115
116 nc_verbosity(NC_VERB_VERBOSE);
117
118 ret = nc_client_ssh_set_username("username");
119 assert_int_equal(ret, 0);
Fred Gan3a736e02021-01-04 17:59:38 +0800120 ret = nc_client_ssh_ch_set_username("ch_username");
121 assert_int_equal(ret, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200122 nc_client_ssh_set_auth_hostkey_check_clb(ssh_hostkey_check_clb, NULL);
123
124 return 0;
125}
126
127static int
128teardown_f(void **state)
129{
130 (void)state;
roman33ef8712023-02-17 10:25:12 +0100131 nc_client_destroy();
David Sedlákddde4492018-09-30 21:34:38 +0200132 return 0;
133}
134
135MOCK int
136__wrap_connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
137{
138 (void)sockfd;
139 (void)addr;
140 (void)addrlen;
141
142 return (int)mock();
143}
144
145MOCK int
146__wrap_ssh_connect(ssh_session session)
147{
148 (void)session;
149
150 /* set support of all authentication methods by fake server */
151 ssh_set_auth_methods(session, SSH_AUTH_METHOD_PUBLICKEY | SSH_AUTH_METHOD_PASSWORD | SSH_AUTH_METHOD_INTERACTIVE);
152 return (int)mock();
153}
154
155MOCK int
156__wrap_ssh_userauth_none(ssh_session session, const char *username)
157{
158 (void)session;
159 (void)username;
160
161 return (int)mock();
162}
163
164MOCK int
165__wrap_ssh_userauth_kbdint(ssh_session session, const char *user, const char *submethods)
166{
167 (void)session;
168 (void)user;
169 (void)submethods;
170
171 return (int)mock();
172}
173
174MOCK int
175__wrap_ssh_is_connected(ssh_session session)
176{
177 (void)session;
178
179 return (int)mock();
180}
181
182MOCK int
183__wrap_ssh_channel_open_session(ssh_channel channel)
184{
185 (void)channel;
186
187 return (int)mock();
188}
189
190MOCK int
191__wrap_ssh_channel_request_subsystem(ssh_channel channel, const char *subsystem)
192{
193 (void)channel;
194 (void)subsystem;
195
196 return (int)mock();
197}
198
199MOCK int
200__wrap_ssh_channel_is_closed(ssh_channel channel)
201{
202 (void)channel;
203
204 return 0;
205}
206
207MOCK int
208__wrap_ssh_channel_write(ssh_channel channel, const void *data, uint32_t len)
209{
210 (void)channel;
211 (void)data;
212
213 return len;
214}
215
216MOCK int
217__wrap_ssh_channel_poll_timeout(ssh_channel channel, int timeout, int is_stderr)
218{
219 (void)channel;
220 (void)timeout;
221 (void)is_stderr;
222
223 return (int)mock();
224}
225
226MOCK int
227__wrap_ssh_userauth_password(ssh_session session, const char *username, const char *password)
228{
229 (void)session;
230 check_expected(password);
231 check_expected(username);
232
David Sedlákddde4492018-09-30 21:34:38 +0200233 return (int)mock();
234}
235
236MOCK int
237__wrap_nc_handshake_io(struct nc_session *session)
238{
239 (void)session;
240
241 return (int)mock();
242}
243
244MOCK int
245__wrap_nc_ctx_check_and_fill(struct nc_session *session)
246{
247 (void)session;
248
249 return (int)mock();
250}
251
David Sedlák77acc202018-10-08 21:44:14 +0200252MOCK int
253__wrap_ssh_userauth_try_publickey(ssh_session session, const char *username, const ssh_key pubkey)
254{
255 (void)session;
256 (void)username;
257 (void)pubkey;
258
259 return (int)mock();
260}
261
262MOCK int
263__wrap_ssh_userauth_publickey(ssh_session session, const char *username, const ssh_key privkey)
264{
265 (void)session;
266 (void)username;
267 (void)privkey;
268
269 return (int)mock();
270}
271
Fred Gan3a736e02021-01-04 17:59:38 +0800272MOCK int
273__wrap_nc_sock_listen_inet(const char *address, uint16_t port, struct nc_keepalives *ka)
274{
275 (void)address;
276 (void)port;
277 (void)ka;
278
279 return (int)mock();
280}
281
282MOCK int
283__wrap_nc_sock_accept_binds(struct nc_bind *binds, uint16_t bind_count, int timeout, char **host, uint16_t *port, uint16_t *idx)
284{
285 (void)binds;
286 (void)bind_count;
287 (void)timeout;
288 (void)host;
289 (void)port;
290
291 *idx = 0;
292 return (int)mock();
293}
294
295MOCK struct nc_session *
296__wrap_nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly_ctx *ctx, int timeout)
297{
298 (void)sock;
299 (void)host;
300 (void)port;
301 (void)ctx;
302 (void)timeout;
303
304 return mock_ptr_type(struct nc_session *);
305}
306
David Sedlákddde4492018-09-30 21:34:38 +0200307static int
308test_hostkey_clb(const char *hostname, ssh_session session, void *priv)
309{
310 (void)hostname;
311 (void)session;
312 (void)priv;
313
314 return 0;
315}
316
317static void
318test_nc_client_ssh_setting_auth_hostkey_check_clb(void **state)
319{
320 (void)state;
321 int (*ret_f)(const char *hostname, ssh_session session, void *priv);
322 char *priv_data_ret;
323
324 /* ssh_hostkey_check_clb is set in setup_f */
325 nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
326 assert_ptr_equal(ret_f, ssh_hostkey_check_clb);
327 assert_null(priv_data_ret);
328
329 /* set different callback and private data */
330 nc_client_ssh_set_auth_hostkey_check_clb(test_hostkey_clb, "DATA");
331 nc_client_ssh_get_auth_hostkey_check_clb(&ret_f, (void **)&priv_data_ret);
332 assert_ptr_equal(ret_f, test_hostkey_clb);
333 assert_string_equal(priv_data_ret, "DATA");
334}
335
336char *
337test_pwd_clb1(const char *username, const char *hostname, void *priv)
338{
339 char *pass, *pass_to_return;
340
341 check_expected(username);
342 check_expected(hostname);
343 check_expected(priv);
344
345 pass = (char *)mock();
346 pass_to_return = malloc(sizeof *pass * (strlen(pass) + 1));
347 strcpy(pass_to_return, pass);
348
349 return pass_to_return;
350}
351
352char *
353test_pwd_clb2(const char *username, const char *hostname, void *priv)
354{
355 (void)username;
356 (void)hostname;
357 (void)priv;
358
359 return 0;
360}
361
362static void
363test_nc_client_ssh_setting_auth_password_clb(void **state)
364{
365 (void)state;
366 char *(*ret_f)(const char *username, const char *hostname, void *priv);
367 char *priv_data_ret;
368
369 /* set callback */
370 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "DATA");
371 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
372 assert_ptr_equal(test_pwd_clb1, ret_f);
373 assert_string_equal("DATA", priv_data_ret);
374
375 /* set different callback */
376 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, "NEW DATA");
377 nc_client_ssh_get_auth_password_clb(&ret_f, (void **)&priv_data_ret);
378 assert_ptr_equal(test_pwd_clb2, ret_f);
379 assert_string_equal("NEW DATA", priv_data_ret);
380}
381
382char *
383test_inter_clb1(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
384{
385 (void)auth_name;
386 (void)instruction;
387 (void)prompt;
388 (void)echo;
389 (void)priv;
390
391 return 0;
392}
393
394char *
395test_inter_clb2(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv)
396{
397 (void)auth_name;
398 (void)instruction;
399 (void)prompt;
400 (void)echo;
401 (void)priv;
402
403 return 0;
404}
405
406static void
407test_nc_client_ssh_setting_auth_interactive_clb(void **state)
408{
409 (void)state;
410 char *(*ret_f)(const char *auth_name, const char *instruction, const char *prompt, int echo, void *priv);
411 char *priv_data_ret;
412
413 /* set callback */
414 nc_client_ssh_set_auth_interactive_clb(test_inter_clb1, "DATA");
415 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
416 assert_ptr_equal(test_inter_clb1, ret_f);
417 assert_string_equal("DATA", priv_data_ret);
418
419 /* set diferent callback */
420 nc_client_ssh_set_auth_interactive_clb(test_inter_clb2, "NEW DATA");
421 nc_client_ssh_get_auth_interactive_clb(&ret_f, (void **)&priv_data_ret);
422 assert_ptr_equal(test_inter_clb2, ret_f);
423 assert_string_equal("NEW DATA", priv_data_ret);
424}
425
426char *
427test_passphrase_clb1(const char *privkey_path, void *priv)
428{
429 (void)privkey_path;
430 (void)priv;
431
432 return 0;
433}
434
435char *
436test_passphrase_clb2(const char *privkey_path, void *priv)
437{
438 (void)privkey_path;
439 (void)priv;
440
441 return 0;
442}
443
444static void
445test_nc_client_ssh_setting_auth_privkey_passphrase_clb(void **state)
446{
447 (void)state;
448 char *(*ret_f)(const char *privkey_path, void *priv);
449 char *priv_data_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200450
David Sedlákddde4492018-09-30 21:34:38 +0200451 /* set first callback */
452 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb1, "DATA");
453 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
454 assert_ptr_equal(ret_f, test_passphrase_clb1);
455 assert_string_equal("DATA", priv_data_ret);
456
457 /* set different callback */
458 nc_client_ssh_set_auth_privkey_passphrase_clb(test_passphrase_clb2, "NEW DATA");
459 nc_client_ssh_get_auth_privkey_passphrase_clb(&ret_f, (void **)&priv_data_ret);
460 assert_ptr_equal(ret_f, test_passphrase_clb2);
461 assert_string_equal("NEW DATA", priv_data_ret);
462}
463
464static void
465test_nc_client_ssh_adding_keypair(void **state)
466{
467 (void)state;
468 int ret;
469 const char *pubkey1, *pubkey2;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200470
David Sedlákddde4492018-09-30 21:34:38 +0200471 /* at the beginning keypair count should be 0 */
472 ret = nc_client_ssh_get_keypair_count();
473 assert_int_equal(ret, 0);
474
475 /* add first key pair */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200476 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 +0200477 assert_int_equal(ret, 0);
478 ret = nc_client_ssh_get_keypair_count();
479 assert_int_equal(ret, 1);
480
481 /* add second keypair */
482 ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
483 assert_int_equal(ret, 0);
484 ret = nc_client_ssh_get_keypair_count();
485 assert_int_equal(ret, 2);
486 ret = nc_client_ssh_get_keypair(1, &pubkey1, &pubkey2);
487 assert_int_equal(ret, 0);
488 assert_string_equal(pubkey1, "key_pub");
489 assert_string_equal(pubkey2, "key_priv");
490
491 /* delete first keypair */
492 ret = nc_client_ssh_del_keypair(0);
493 assert_int_equal(ret, 0);
494 ret = nc_client_ssh_get_keypair_count();
495 assert_int_equal(ret, 1);
496 /* try to get deleted keypair */
497 ret = nc_client_ssh_get_keypair(5, &pubkey1, &pubkey2);
498 assert_int_equal(ret, -1);
499
500 /* try to add keypair that is already set */
501 ret = nc_client_ssh_add_keypair("key_pub", "key_priv");
502 assert_int_equal(ret, -1);
503 ret = nc_client_ssh_get_keypair_count();
504 assert_int_equal(ret, 1);
505
506 /* try to delete keypair with id that is not used */
507 ret = nc_client_ssh_del_keypair(42);
508 assert_int_equal(ret, -1);
509 ret = nc_client_ssh_get_keypair_count();
510 assert_int_equal(ret, 1);
511
512 /* remove remaining keypairs */
513 ret = nc_client_ssh_del_keypair(0);
514 assert_int_equal(ret, 0);
515 ret = nc_client_ssh_get_keypair_count();
516 assert_int_equal(ret, 0);
517}
518
519static void
520test_nc_client_ssh_setting_auth_pref(void **state)
521{
522 (void)state;
523 int ret;
524
David Sedlákaae4df32018-10-08 22:27:22 +0200525 /* initiate client, must be called in first test */
David Sedlákddde4492018-09-30 21:34:38 +0200526 nc_client_init();
527
528 /* check default prefference settings according to documentation */
529 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
roman41a11e42022-06-22 09:27:08 +0200530 assert_int_equal(ret, 1);
David Sedlákddde4492018-09-30 21:34:38 +0200531 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
532 assert_int_equal(ret, 2);
533 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
roman41a11e42022-06-22 09:27:08 +0200534 assert_int_equal(ret, 3);
David Sedlákddde4492018-09-30 21:34:38 +0200535
536 /* try to set prefetence of non existing method */
537 nc_client_ssh_set_auth_pref(42, 22);
538
539 /* try to get preference of non existing method */
540 ret = nc_client_ssh_get_auth_pref(42);
541 assert_int_equal(ret, 0);
542
543 /* change values of all methods and check if they actually changed */
544 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 9);
545 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_INTERACTIVE);
546 assert_int_equal(ret, 9);
547
548 /* negative value should be set as -1 */
549 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -5);
550 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PASSWORD);
551 assert_int_equal(ret, -1);
552
553 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 11);
554 ret = nc_client_ssh_get_auth_pref(NC_SSH_AUTH_PUBLICKEY);
555 assert_int_equal(ret, 11);
556}
557
558static void
559test_nc_client_ssh_setting_username(void **state)
560{
561 (void)state;
562 int ret;
563 const char *username_ret;
Michal Vaskob83a3fa2021-05-26 09:53:42 +0200564
David Sedlákddde4492018-09-30 21:34:38 +0200565 username_ret = nc_client_ssh_get_username();
566 /* username is set to "username" in setup_f */
567 assert_string_equal(username_ret, "username");
568
569 /* set new username and check if it changes */
570 ret = nc_client_ssh_set_username("new_username");
571 assert_int_equal(ret, 0);
572 username_ret = nc_client_ssh_get_username();
573 assert_string_equal(username_ret, "new_username");
574}
575
576static void
577test_nc_connect_ssh_interactive_succesfull(void **state)
578{
579 (void)state;
580 struct nc_session *session;
581
582 /* set authentication method to use interactive authentication */
583 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
584 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
585 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
586
587 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 20);
588
589 /* prepare return values for functions used by nc_connect_ssh */
590 will_return(__wrap_connect, 0);
591 will_return(__wrap_ssh_connect, 0);
592 will_return(__wrap_ssh_userauth_none, 1);
593
594 will_return(__wrap_ssh_userauth_kbdint, 0);
595 will_return(__wrap_ssh_is_connected, 1);
596 will_return(__wrap_ssh_is_connected, 1);
597
598 will_return(__wrap_ssh_channel_open_session, 0);
599 will_return(__wrap_ssh_channel_request_subsystem, 0);
600
601 will_return(__wrap_nc_handshake_io, 3);
602 will_return(__wrap_nc_ctx_check_and_fill, 0);
603
604 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
605 assert_non_null(session);
606
Michal Vasko0ab3a662021-07-26 12:17:41 +0200607 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200608 nc_session_free(session, NULL);
609}
610
611static void
612test_nc_connect_ssh_password_succesfull(void **state)
613{
614 (void)state;
615 struct nc_session *session;
616
617 /* set authentication method to use password authentication */
618 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, 1);
619 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, -1);
620 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
621
622 /* set authentication callback */
623 nc_client_ssh_set_auth_password_clb(test_pwd_clb1, "private_data");
624 will_return(test_pwd_clb1, "secret password");
625 /* set values that are expected as parameters for authentication callback */
626 expect_string(test_pwd_clb1, username, "username");
627 expect_string(test_pwd_clb1, hostname, "127.0.0.1");
628 expect_string(test_pwd_clb1, priv, "private_data");
629
630 /* fake succesfull connection */
631 will_return(__wrap_connect, 0);
632 will_return(__wrap_ssh_connect, 0);
633 /* do not authenticate using no authentication method */
634 will_return(__wrap_ssh_userauth_none, 1);
635
636 /* succesfully authenticate via password authentication */
637 expect_string(__wrap_ssh_userauth_password, password, "secret password");
638 expect_string(__wrap_ssh_userauth_password, username, "username");
639 will_return(__wrap_ssh_userauth_password, 0);
640
641 /* fake ssh functions that are used to open netconf channel */
642 will_return(__wrap_ssh_channel_open_session, 0);
643 will_return(__wrap_ssh_channel_request_subsystem, 0);
644
645 /* fake that connection is still alive*/
646 will_return(__wrap_ssh_is_connected, 1);
647
648 /* fake ssh function for recieving hello message */
649 will_return(__wrap_ssh_is_connected, 1);
650
651 will_return(__wrap_nc_handshake_io, 3);
652 will_return(__wrap_nc_ctx_check_and_fill, 0);
653
654 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
655 assert_non_null(session);
656
657 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200658 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlákddde4492018-09-30 21:34:38 +0200659 nc_session_free(session, NULL);
660}
661
662static void
romanc1d2b092023-02-02 08:58:27 +0100663test_nc_connect_ssh_pubkey_ecdsa_succesfull(void **state)
David Sedlák77acc202018-10-08 21:44:14 +0200664{
665 (void)state;
666 struct nc_session *session;
667 int ret = 0;
668
669 /* set authentication method to use password authentication */
670 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
671 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
672 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
673
674 /* add keypair for authentication */
Michal Vasko7a4213f2022-09-08 11:02:34 +0200675 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 +0200676 assert_int_equal(ret, 0);
677
678 /* fake succesfull connection */
679 will_return(__wrap_connect, 0);
680 will_return(__wrap_ssh_connect, 0);
681 /* do not authenticate using no authentication method */
682 will_return(__wrap_ssh_userauth_none, 1);
683 will_return(__wrap_ssh_userauth_try_publickey, 0);
684 will_return(__wrap_ssh_userauth_publickey, 0);
685 will_return(__wrap_ssh_is_connected, 1);
686 will_return(__wrap_ssh_channel_open_session, 0);
687 will_return(__wrap_ssh_channel_request_subsystem, 0);
688
689 /* fake ssh function for recieving hello message */
690 will_return(__wrap_ssh_is_connected, 1);
691
692 will_return(__wrap_nc_handshake_io, 3);
693 will_return(__wrap_nc_ctx_check_and_fill, 0);
694 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
695 assert_non_null(session);
696
697 /* disconnect */
Michal Vasko0ab3a662021-07-26 12:17:41 +0200698 will_return(__wrap_ssh_channel_poll_timeout, 0);
David Sedlák77acc202018-10-08 21:44:14 +0200699 nc_session_free(session, NULL);
romanc1d2b092023-02-02 08:58:27 +0100700
701 /* delete the keypair */
702 ret = nc_client_ssh_del_keypair(0);
703 assert_int_equal(ret, 0);
704}
705
706static void
707test_nc_connect_ssh_pubkey_succesfull(void **state)
708{
709 (void)state;
710 struct nc_session *session;
711 struct ly_ctx *ctx;
712 struct lyd_node *tree;
713 int ret = 0;
714
715 /* set authentication method to use password authentication */
716 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
717 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
718 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, -1);
719
720 /* add keypair for authentication */
721 ret = nc_client_ssh_add_keypair(TESTS_DIR "/data/key_rsa.pub", TESTS_DIR "/data/key_rsa");
722 assert_int_equal(ret, 0);
723
724 /* fake succesfull connection */
725 will_return(__wrap_connect, 0);
726 will_return(__wrap_ssh_connect, 0);
roman33ef8712023-02-17 10:25:12 +0100727 will_return(__wrap_nc_sock_listen_inet, 0);
romanc1d2b092023-02-02 08:58:27 +0100728 /* do not authenticate using no authentication method */
729 will_return(__wrap_ssh_userauth_none, 1);
730 will_return(__wrap_ssh_userauth_try_publickey, 0);
731 will_return(__wrap_ssh_userauth_publickey, 0);
732 will_return(__wrap_ssh_is_connected, 1);
733 will_return(__wrap_ssh_channel_open_session, 0);
734 will_return(__wrap_ssh_channel_request_subsystem, 0);
735
736 /* fake ssh function for recieving hello message */
737 will_return(__wrap_ssh_is_connected, 1);
738
739 will_return(__wrap_nc_handshake_io, 3);
740 will_return(__wrap_nc_ctx_check_and_fill, 0);
741
742 ret = ly_ctx_new(MODULES_DIR, 0, &ctx);
743 assert_int_equal(ret, 0);
744
745 ret = nc_server_config_load_modules(&ctx);
746 assert_int_equal(ret, 0);
747
748 ret = lyd_parse_data_mem(ctx, data, LYD_XML, LYD_PARSE_NO_STATE | LYD_PARSE_STRICT, LYD_VALIDATE_NO_STATE, &tree);
749 assert_int_equal(ret, 0);
750
751 ret = nc_server_config_setup(tree);
752 assert_int_equal(ret, 0);
753
754 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
755 assert_non_null(session);
756
757 /* disconnect */
758 will_return(__wrap_ssh_channel_poll_timeout, 0);
roman33ef8712023-02-17 10:25:12 +0100759
760 /* free everything used */
romanc1d2b092023-02-02 08:58:27 +0100761 nc_session_free(session, NULL);
roman33ef8712023-02-17 10:25:12 +0100762 lyd_free_all(tree);
763 nc_server_destroy();
764 ly_ctx_destroy(ctx);
David Sedlák77acc202018-10-08 21:44:14 +0200765}
766
767static void
David Sedlákddde4492018-09-30 21:34:38 +0200768test_nc_connect_connection_failed(void **state)
769{
770 (void)state;
771 struct nc_session *session;
772
773 errno = ECONNREFUSED;
774 will_return(__wrap_connect, -1);
775 will_return(__wrap_ssh_is_connected, 0);
776
777 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
778 assert_null(session);
779}
780
781static void
782test_nc_connect_ssh_bad_hello(void **state)
783{
784 (void)state;
785 struct nc_session *session;
786
787 /* set authentication method to use interactive authentication */
788 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 1);
789 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PASSWORD, -1);
790 nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 1);
791
792 nc_client_ssh_set_auth_password_clb(test_pwd_clb2, NULL);
793
794 will_return(__wrap_connect, 0);
795 will_return(__wrap_ssh_connect, 0);
796 will_return(__wrap_ssh_userauth_none, 1);
797
798 will_return(__wrap_ssh_userauth_kbdint, 0);
799 will_return(__wrap_ssh_is_connected, 1);
800 will_return(__wrap_ssh_is_connected, 1);
801
802 will_return(__wrap_ssh_channel_open_session, 0);
803 will_return(__wrap_ssh_channel_request_subsystem, 0);
804 will_return(__wrap_nc_handshake_io, 4);
805
806 session = nc_connect_ssh("127.0.0.1", 8080, NULL);
807 assert_null(session);
808
David Sedlákaae4df32018-10-08 22:27:22 +0200809 /* destroy client, must be called in last test */
David Sedlákddde4492018-09-30 21:34:38 +0200810 nc_client_destroy();
811}
812
Fred Gan3a736e02021-01-04 17:59:38 +0800813static void
814test_nc_client_ssh_ch_setting_username(void **state)
815{
816 (void)state;
817 const char *username_ret;
818 int ret;
819
820 /* username is set to "ch_username" in setup_f */
821 username_ret = nc_client_ssh_ch_get_username();
822 assert_string_equal(username_ret, "ch_username");
823 /* set new username and check if it changes */
824 ret = nc_client_ssh_ch_set_username("new_ch_username");
825 assert_int_equal(ret, 0);
826 username_ret = nc_client_ssh_ch_get_username();
827 assert_string_equal(username_ret, "new_ch_username");
828}
829
830static void
831test_nc_client_ssh_ch_add_bind_listen(void **state)
832{
833 (void)state;
834 int ret;
835
836 /* invalid parameters, address NULL or port 0 */
837 ret = nc_client_ssh_ch_add_bind_listen(NULL, 4334);
838 assert_int_equal(ret, -1);
839 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 0);
840 assert_int_equal(ret, -1);
841
842 /* failed to create an ssh listening socket */
843 will_return(__wrap_nc_sock_listen_inet, -1);
844 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
845 assert_int_equal(ret, -1);
846
847 /* fake a successful CH ssh listening socket */
848 will_return(__wrap_nc_sock_listen_inet, 1);
849 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
850 assert_int_equal(ret, 0);
851
852 /* remove ssh listening client binds */
853 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
854 assert_int_equal(ret, 0);
855}
856
857static void
858test_nc_accept_callhome(void **state)
859{
860 (void)state;
861 struct nc_session *session = NULL;
862 int timeout = 10;
863 int ret;
864
865 /* invalid parameter session */
866 ret = nc_accept_callhome(timeout, NULL, NULL);
867 assert_int_equal(ret, -1);
868
869 /* no client bind */
870 ret = nc_accept_callhome(timeout, NULL, &session);
871 assert_int_equal(ret, -1);
872
873 /* successfully add a client Call Home bind */
874 will_return(__wrap_nc_sock_listen_inet, 1);
875 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
876 assert_int_equal(ret, 0);
877
878 /* failed to accept a client bind */
879 will_return(__wrap_nc_sock_accept_binds, -1);
880 ret = nc_accept_callhome(timeout, NULL, &session);
881 assert_int_equal(ret, -1);
882
883 /* failed to accept a server Call Home connection */
884 will_return(__wrap_nc_accept_callhome_ssh_sock, NULL);
885 will_return(__wrap_nc_sock_accept_binds, 2);
886 ret = nc_accept_callhome(timeout, NULL, &session);
887 assert_int_equal(ret, -1);
888
889 /* create session structure to fake a successful server call home connection */
890 session = nc_new_session(NC_CLIENT, 0);
891 assert_non_null(session);
892 will_return(__wrap_nc_sock_accept_binds, 2);
893 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
894 ret = nc_accept_callhome(timeout, NULL, &session);
895 assert_int_equal(ret, 1);
896
897 /* remove ssh listening client binds */
898 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
899 assert_int_equal(ret, 0);
900
901 /* free session */
902 nc_session_free(session, NULL);
903}
904
905static void
906test_nc_client_ssh_callhome_successful(void **state)
907{
908 (void)state;
909 struct nc_session *session = NULL;
910 int timeout = 10;
911 int ret;
912
913 /* create session structure */
914 session = nc_new_session(NC_CLIENT, 0);
915 assert_non_null(session);
916
917 /* prepare to fake return values for functions used by nc_accept_callhome */
918 will_return(__wrap_nc_sock_listen_inet, 1);
919 will_return(__wrap_nc_sock_accept_binds, 2);
920 will_return(__wrap_nc_accept_callhome_ssh_sock, session);
921
922 ret = nc_client_ssh_ch_add_bind_listen("127.0.0.1", 4334);
923 assert_int_equal(ret, 0);
924 ret = nc_accept_callhome(timeout, NULL, &session);
925 assert_int_equal(ret, 1);
926
927 /* remove ssh listening client binds */
928 ret = nc_client_ssh_ch_del_bind("127.0.0.1", 4334);
929 assert_int_equal(ret, 0);
930
931 /* free session */
932 nc_session_free(session, NULL);
933}
934
David Sedlákddde4492018-09-30 21:34:38 +0200935int
936main(void)
937{
938 const struct CMUnitTest tests[] = {
939 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_pref, setup_f, teardown_f),
940 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_hostkey_check_clb, setup_f, teardown_f),
941 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_password_clb, setup_f, teardown_f),
942 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_interactive_clb, setup_f, teardown_f),
943 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_auth_privkey_passphrase_clb, setup_f, teardown_f),
944 cmocka_unit_test_setup_teardown(test_nc_client_ssh_adding_keypair, setup_f, teardown_f),
945 cmocka_unit_test_setup_teardown(test_nc_client_ssh_setting_username, setup_f, teardown_f),
946 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_interactive_succesfull, setup_f, teardown_f),
947 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_password_succesfull, setup_f, teardown_f),
romanc1d2b092023-02-02 08:58:27 +0100948 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_ecdsa_succesfull, setup_f, teardown_f),
David Sedlák77acc202018-10-08 21:44:14 +0200949 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_pubkey_succesfull, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200950 cmocka_unit_test_setup_teardown(test_nc_connect_connection_failed, setup_f, teardown_f),
951 cmocka_unit_test_setup_teardown(test_nc_connect_ssh_bad_hello, setup_f, teardown_f),
Fred Gan3a736e02021-01-04 17:59:38 +0800952 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_setting_username, setup_f, teardown_f),
953 cmocka_unit_test_setup_teardown(test_nc_client_ssh_ch_add_bind_listen, setup_f, teardown_f),
954 cmocka_unit_test_setup_teardown(test_nc_accept_callhome, setup_f, teardown_f),
955 cmocka_unit_test_setup_teardown(test_nc_client_ssh_callhome_successful, setup_f, teardown_f),
David Sedlákddde4492018-09-30 21:34:38 +0200956 };
957
958 return cmocka_run_group_tests(tests, NULL, NULL);
959}