From 31ceec02fe5409b715dc30da63864dd3b9b3f9de Mon Sep 17 00:00:00 2001 From: Jakub Jelen Date: Tue, 27 Jan 2026 16:07:25 +0100 Subject: [PATCH] misc: Cache user home directory in session MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Jakub Jelen Reviewed-by: Pavol Žáčik Reviewed-by: Andreas Schneider --- include/libssh/misc.h | 2 +- include/libssh/session.h | 1 + src/misc.c | 30 ++++++++++++++++++++++++++---- src/session.c | 1 + tests/unittests/torture_misc.c | 2 +- 5 files changed, 30 insertions(+), 6 deletions(-) diff --git a/include/libssh/misc.h b/include/libssh/misc.h index ab726a0e..d62afffd 100644 --- a/include/libssh/misc.h +++ b/include/libssh/misc.h @@ -43,7 +43,7 @@ extern "C" { /* in misc.c */ /* gets the user home dir. */ -char *ssh_get_user_home_dir(void); +char *ssh_get_user_home_dir(ssh_session session); char *ssh_get_local_username(void); int ssh_file_readaccess_ok(const char *file); int ssh_dir_writeable(const char *path); diff --git a/include/libssh/session.h b/include/libssh/session.h index 51fe6890..9c161285 100644 --- a/include/libssh/session.h +++ b/include/libssh/session.h @@ -253,6 +253,7 @@ struct ssh_session_struct { char *username; char *host; char *bindaddr; /* bind the client to an ip addr */ + char *homedir; char *sshdir; char *knownhosts; char *global_knownhosts; diff --git a/src/misc.c b/src/misc.c index 1432469f..2c1e30fc 100644 --- a/src/misc.c +++ b/src/misc.c @@ -108,7 +108,7 @@ */ #ifdef _WIN32 -char *ssh_get_user_home_dir(void) +static char *ssh_get_user_home_dir_internal(void) { char tmp[PATH_MAX] = {0}; char *szPath = NULL; @@ -298,7 +298,7 @@ int ssh_is_ipaddr(const char *str) #define NSS_BUFLEN_PASSWD 4096 #endif /* NSS_BUFLEN_PASSWD */ -char *ssh_get_user_home_dir(void) +static char *ssh_get_user_home_dir_internal(void) { char *szPath = NULL; struct passwd pwd; @@ -313,7 +313,6 @@ char *ssh_get_user_home_dir(void) return NULL; } snprintf(buf, sizeof(buf), "%s", szPath); - return strdup(buf); } @@ -428,6 +427,29 @@ int ssh_is_ipaddr(const char *str) #endif /* _WIN32 */ +char *ssh_get_user_home_dir(ssh_session session) +{ + char *szPath = NULL; + + /* If used previously, reuse cached value */ + if (session != NULL && session->opts.homedir != NULL) { + return strdup(session->opts.homedir); + } + + szPath = ssh_get_user_home_dir_internal(); + if (szPath == NULL) { + return NULL; + } + + if (session != NULL) { + /* cache it: + * failure is not fatal -- at worst we will just not cache it */ + session->opts.homedir = strdup(szPath); + } + + return szPath; +} + char *ssh_lowercase(const char* str) { char *new = NULL, *p = NULL; @@ -1189,7 +1211,7 @@ char *ssh_path_expand_tilde(const char *d) } else { ld = strlen(d); p = (char *) d; - h = ssh_get_user_home_dir(); + h = ssh_get_user_home_dir(NULL); } if (h == NULL) { return NULL; diff --git a/src/session.c b/src/session.c index 6ee217f9..7ed4a98b 100644 --- a/src/session.c +++ b/src/session.c @@ -405,6 +405,7 @@ void ssh_free(ssh_session session) SAFE_FREE(session->opts.bindaddr); SAFE_FREE(session->opts.username); SAFE_FREE(session->opts.host); + SAFE_FREE(session->opts.homedir); SAFE_FREE(session->opts.sshdir); SAFE_FREE(session->opts.knownhosts); SAFE_FREE(session->opts.global_knownhosts); diff --git a/tests/unittests/torture_misc.c b/tests/unittests/torture_misc.c index b2320a94..7d311afc 100644 --- a/tests/unittests/torture_misc.c +++ b/tests/unittests/torture_misc.c @@ -52,7 +52,7 @@ static void torture_get_user_home_dir(void **state) { (void) state; - user = ssh_get_user_home_dir(); + user = ssh_get_user_home_dir(NULL); assert_non_null(user); #ifndef _WIN32 assert_string_equal(user, pwd->pw_dir);