@@ -401,12 +401,56 @@ nc_client_ssh_do_dnssec_sshfp_check(ssh_session session, enum ssh_keytypes_e srv
401401
402402#endif
403403
404+ /**
405+ * @brief Convert knownhosts mode to string.
406+ *
407+ * @param[in] knownhosts_mode Knownhosts mode.
408+ * @return Knownhosts mode string.
409+ */
410+ static const char *
411+ nc_client_ssh_knownhosts_mode2str (NC_SSH_KNOWNHOSTS_MODE knownhosts_mode )
412+ {
413+ const char * mode_str ;
414+
415+ switch (knownhosts_mode ) {
416+ case NC_SSH_KNOWNHOSTS_ASK :
417+ mode_str = "ask" ;
418+ break ;
419+ case NC_SSH_KNOWNHOSTS_STRICT :
420+ mode_str = "strict" ;
421+ break ;
422+ case NC_SSH_KNOWNHOSTS_ACCEPT_NEW :
423+ mode_str = "accept-new" ;
424+ break ;
425+ case NC_SSH_KNOWNHOSTS_ACCEPT :
426+ mode_str = "accept" ;
427+ break ;
428+ case NC_SSH_KNOWNHOSTS_SKIP :
429+ mode_str = "skip" ;
430+ break ;
431+ default :
432+ mode_str = "unknown" ;
433+ break ;
434+ }
435+
436+ return mode_str ;
437+ }
438+
439+ /**
440+ * @brief Perform the hostkey check.
441+ *
442+ * @param[in] hostname Expected hostname.
443+ * @param[in] port Expected port.
444+ * @param[in] knownhosts_mode Knownhosts mode.
445+ * @param[in] session libssh session.
446+ * @return 0 on success, -1 on error.
447+ */
404448static int
405- nc_client_ssh_auth_hostkey_check (const char * hostname , uint16_t port , ssh_session session )
449+ nc_client_ssh_auth_hostkey_check (const char * hostname , uint16_t port ,
450+ NC_SSH_KNOWNHOSTS_MODE knownhosts_mode , ssh_session session )
406451{
407452 char * hexa = NULL ;
408453 unsigned char * hash_sha1 = NULL ;
409- NC_SSH_KNOWNHOSTS_MODE knownhosts_mode = ssh_opts .knownhosts_mode ;
410454 enum ssh_keytypes_e srv_pubkey_type ;
411455 int state ;
412456
@@ -420,6 +464,8 @@ nc_client_ssh_auth_hostkey_check(const char *hostname, uint16_t port, ssh_sessio
420464 int dnssec_ret ;
421465#endif
422466
467+ VRB (NULL , "Server hostkey check mode: %s." , nc_client_ssh_knownhosts_mode2str (knownhosts_mode ));
468+
423469 if (knownhosts_mode == NC_SSH_KNOWNHOSTS_SKIP ) {
424470 /* skip all hostkey checks */
425471 return 0 ;
@@ -744,28 +790,46 @@ sshauth_privkey_passphrase(const char *privkey_path, void *UNUSED(priv))
744790#endif
745791}
746792
747- API int
748- nc_client_ssh_set_knownhosts_path (const char * path )
793+ static int
794+ _nc_client_ssh_set_knownhosts_path (const char * path , struct nc_client_ssh_opts * opts )
749795{
750- free (ssh_opts . knownhosts_path );
796+ free (opts -> knownhosts_path );
751797
752798 if (!path ) {
753- ssh_opts . knownhosts_path = NULL ;
799+ opts -> knownhosts_path = NULL ;
754800 return 0 ;
755801 }
756802
757- ssh_opts . knownhosts_path = strdup (path );
758- NC_CHECK_ERRMEM_RET (!ssh_opts . knownhosts_path , 1 );
803+ opts -> knownhosts_path = strdup (path );
804+ NC_CHECK_ERRMEM_RET (!opts -> knownhosts_path , 1 );
759805
760806 return 0 ;
761807}
762808
809+ API int
810+ nc_client_ssh_set_knownhosts_path (const char * path )
811+ {
812+ return _nc_client_ssh_set_knownhosts_path (path , & ssh_opts );
813+ }
814+
815+ API int
816+ nc_client_ssh_ch_set_knownhosts_path (const char * path )
817+ {
818+ return _nc_client_ssh_set_knownhosts_path (path , & ssh_ch_opts );
819+ }
820+
763821API void
764822nc_client_ssh_set_knownhosts_mode (NC_SSH_KNOWNHOSTS_MODE mode )
765823{
766824 ssh_opts .knownhosts_mode = mode ;
767825}
768826
827+ API void
828+ nc_client_ssh_ch_set_knownhosts_mode (NC_SSH_KNOWNHOSTS_MODE mode )
829+ {
830+ ssh_ch_opts .knownhosts_mode = mode ;
831+ }
832+
769833static void
770834_nc_client_ssh_set_auth_password_clb (char * (* auth_password )(const char * username , const char * hostname , void * priv ),
771835 void * priv , struct nc_client_ssh_opts * opts )
@@ -1254,7 +1318,7 @@ connect_ssh_session(struct nc_session *session, struct nc_client_ssh_opts *opts,
12541318 return -1 ;
12551319 }
12561320
1257- if (nc_client_ssh_auth_hostkey_check (session -> host , session -> port , ssh_sess )) {
1321+ if (nc_client_ssh_auth_hostkey_check (session -> host , session -> port , opts -> knownhosts_mode , ssh_sess )) {
12581322 ERR (session , "Checking the host key failed." );
12591323 return -1 ;
12601324 }
@@ -1701,7 +1765,6 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
17011765 struct nc_session * session = NULL ;
17021766 char * buf = NULL ;
17031767 size_t buf_len = 0 ;
1704- char * known_hosts_path = NULL ;
17051768
17061769 /* process parameters */
17071770 if (!host || (host [0 ] == '\0' )) {
@@ -1727,15 +1790,6 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
17271790 pw = nc_getpw (0 , username , & pw_buf , & buf , & buf_len );
17281791 }
17291792
1730- if (ssh_opts .knownhosts_path ) {
1731- /* known_hosts file path was set so use it */
1732- known_hosts_path = strdup (ssh_opts .knownhosts_path );
1733- NC_CHECK_ERRMEM_GOTO (!known_hosts_path , , fail );
1734- } else if (pw ) {
1735- /* path not set explicitly, but current user's username found in /etc/passwd, so create the path */
1736- NC_CHECK_ERRMEM_GOTO (asprintf (& known_hosts_path , "%s/.ssh/known_hosts" , pw -> pw_dir ) == -1 , , fail );
1737- }
1738-
17391793 /* prepare session structure */
17401794 session = nc_new_session (NC_CLIENT , 0 );
17411795 NC_CHECK_ERRMEM_GOTO (!session , , fail );
@@ -1757,8 +1811,8 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
17571811 ssh_options_set (session -> ti .libssh .session , SSH_OPTIONS_PORT , & port_uint );
17581812 ssh_options_set (session -> ti .libssh .session , SSH_OPTIONS_USER , username );
17591813 ssh_options_set (session -> ti .libssh .session , SSH_OPTIONS_TIMEOUT , & timeout );
1760- if (known_hosts_path ) {
1761- ssh_options_set (session -> ti .libssh .session , SSH_OPTIONS_KNOWNHOSTS , known_hosts_path );
1814+ if (ssh_opts . knownhosts_path ) {
1815+ ssh_options_set (session -> ti .libssh .session , SSH_OPTIONS_KNOWNHOSTS , ssh_opts . knownhosts_path );
17621816 }
17631817
17641818 /* create and assign communication socket */
@@ -1800,12 +1854,10 @@ nc_connect_ssh(const char *host, uint16_t port, struct ly_ctx *ctx)
18001854 session -> port = port ;
18011855
18021856 free (buf );
1803- free (known_hosts_path );
18041857 return session ;
18051858
18061859fail :
18071860 free (buf );
1808- free (known_hosts_path );
18091861 free (ip_host );
18101862 nc_session_free (session , NULL );
18111863 return NULL ;
@@ -1922,6 +1974,10 @@ nc_accept_callhome_ssh_sock(int sock, const char *host, uint16_t port, struct ly
19221974 ssh_options_set (sess , SSH_OPTIONS_USER , ssh_ch_opts .username );
19231975 }
19241976
1977+ if (ssh_ch_opts .knownhosts_path ) {
1978+ ssh_options_set (sess , SSH_OPTIONS_KNOWNHOSTS , ssh_ch_opts .knownhosts_path );
1979+ }
1980+
19251981 ssh_options_set (sess , SSH_OPTIONS_HOSTKEYS , "ssh-ed25519,ecdsa-sha2-nistp256,"
19261982 "ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,ssh-rsa,rsa-sha2-512,rsa-sha2-256,ssh-dss" );
19271983#ifdef HAVE_LIBSSH_OPTIONS_PUBLICKEY_ACCEPTED_TYPES
0 commit comments