diff options
author | Daniel Stenberg <daniel@haxx.se> | 2021-11-19 16:11:29 +0100 |
---|---|---|
committer | Daniel Stenberg <daniel@haxx.se> | 2021-11-29 00:57:22 +0100 |
commit | 2be1aa619bca699e2850baf53c7cc3561f1c1ac2 (patch) | |
tree | 0b759c0c277743c009eaabadaa2402ada108f378 /src | |
parent | 230bb3e278877a8e99179f4df1893ee408d7baf5 (diff) | |
download | curl-2be1aa619bca699e2850baf53c7cc3561f1c1ac2.tar.gz |
tool_findfile: search for a file in the homedir
The homedir() function is now renamed into findfile() and iterates over
all the environment variables trying to access the file in question
until it finds it. Last resort is then getpwuid() if
available. Previously it would first try to find a home directory and if
that was set, insist on checking only that directory for the file. This
now returns the full file name it finds.
The Windows specific checks are now done differently too and in this
order:
1 - %USERPROFILE%
2 - %APPDATA%
3 - %USERPROFILE%\\Application Data
The windows order is modified to match how the Windows 10 ssh tool works
when it searches for .ssh/known_hosts.
Reported-by: jeffrson on github
Co-authored-by: Jay Satiro
Fixes #8033
Closes #8035
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.inc | 4 | ||||
-rw-r--r-- | src/tool_findfile.c | 134 | ||||
-rw-r--r-- | src/tool_findfile.h (renamed from src/tool_homedir.h) | 4 | ||||
-rw-r--r-- | src/tool_homedir.c | 132 | ||||
-rw-r--r-- | src/tool_operate.c | 24 | ||||
-rw-r--r-- | src/tool_paramhlp.c | 1 | ||||
-rw-r--r-- | src/tool_parsecfg.c | 78 |
7 files changed, 180 insertions, 197 deletions
diff --git a/src/Makefile.inc b/src/Makefile.inc index 9fb9946d6..44cfe0f81 100644 --- a/src/Makefile.inc +++ b/src/Makefile.inc @@ -65,12 +65,12 @@ CURL_CFILES = \ tool_doswin.c \ tool_easysrc.c \ tool_filetime.c \ + tool_findfile.c \ tool_formparse.c \ tool_getparam.c \ tool_getpass.c \ tool_help.c \ tool_helpers.c \ - tool_homedir.c \ tool_hugehelp.c \ tool_libinfo.c \ tool_listhelp.c \ @@ -108,12 +108,12 @@ CURL_HFILES = \ tool_doswin.h \ tool_easysrc.h \ tool_filetime.h \ + tool_findfile.h \ tool_formparse.h \ tool_getparam.h \ tool_getpass.h \ tool_help.h \ tool_helpers.h \ - tool_homedir.h \ tool_hugehelp.h \ tool_libinfo.h \ tool_main.h \ diff --git a/src/tool_findfile.c b/src/tool_findfile.c new file mode 100644 index 000000000..cda8c8ed8 --- /dev/null +++ b/src/tool_findfile.c @@ -0,0 +1,134 @@ +/*************************************************************************** + * _ _ ____ _ + * Project ___| | | | _ \| | + * / __| | | | |_) | | + * | (__| |_| | _ <| |___ + * \___|\___/|_| \_\_____| + * + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. + * + * This software is licensed as described in the file COPYING, which + * you should have received as part of this distribution. The terms + * are also available at https://curl.se/docs/copyright.html. + * + * You may opt to use, copy, modify, merge, publish, distribute and/or sell + * copies of the Software, and permit persons to whom the Software is + * furnished to do so, under the terms of the COPYING file. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ***************************************************************************/ +#include "tool_setup.h" + +#ifdef HAVE_PWD_H +# undef __NO_NET_API /* required for building for AmigaOS */ +# include <pwd.h> +#endif + +#ifdef HAVE_SYS_STAT_H +#include <sys/stat.h> +#endif +#ifdef HAVE_FCNTL_H +#include <fcntl.h> +#endif + +#include <curl/mprintf.h> + +#include "tool_findfile.h" + +#include "memdebug.h" /* keep this as LAST include */ + +struct finder { + const char *env; + const char *append; +}; + +static const struct finder list[] = { + { "CURL_HOME", NULL }, + { "XDG_CONFIG_HOME", NULL }, + { "HOME", NULL }, +#ifdef WIN32 + { "USERPROFILE", NULL }, + { "APPDATA", NULL }, + { "USERPROFILE", "\\Application Data"}, +#endif + { NULL, NULL } +}; + +static char *checkhome(const char *home, const char *fname, bool dotscore) +{ + const char pref[2] = { '.', '_' }; + int i; + for(i = 0; i < (dotscore ? 2 : 1); i++) { + char *c; + if(dotscore) + c = curl_maprintf("%s" DIR_CHAR "%c%s", home, pref[i], &fname[1]); + else + c = curl_maprintf("%s" DIR_CHAR "%s", home, fname); + if(c) { + int fd = open(c, O_RDONLY); + if(fd >= 0) { + char *path = strdup(c); + close(fd); + curl_free(c); + return path; + } + curl_free(c); + } + } + return NULL; +} + +/* + * findfile() - return the full path name of the file. + * + * If 'dotscore' is TRUE, then check for the file first with a leading dot + * and then with a leading underscore. + * + * 1. Iterate over the environment variables in order, and if set, check for + * the given file to be accessed there, then it is a match. + * 2. Non-windows: try getpwuid + */ +char *findfile(const char *fname, bool dotscore) +{ + int i; + DEBUGASSERT(fname && fname[0]); + DEBUGASSERT(!dotscore || (fname[0] == '.')); + + if(!fname[0]) + return NULL; + + for(i = 0; list[i].env; i++) { + char *home = curl_getenv(list[i].env); + if(home) { + char *path; + if(!home[0]) { + curl_free(home); + continue; + } + if(list[i].append) { + char *c = curl_maprintf("%s%s", home, list[i].append); + curl_free(home); + if(!c) + return NULL; + home = c; + } + path = checkhome(home, fname, dotscore); + curl_free(home); + if(path) + return path; + } + } +#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) + { + struct passwd *pw = getpwuid(geteuid()); + if(pw) { + char *home = pw->pw_dir; + if(home && home[0]) + return checkhome(home, fname, FALSE); + } + } +#endif /* PWD-stuff */ + return NULL; +} diff --git a/src/tool_homedir.h b/src/tool_findfile.h index 31e38e96a..0f6a8eb55 100644 --- a/src/tool_homedir.h +++ b/src/tool_findfile.h @@ -7,7 +7,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -23,6 +23,6 @@ ***************************************************************************/ #include "tool_setup.h" -char *homedir(const char *fname); +char *findfile(const char *fname, bool dotscore); #endif /* HEADER_CURL_TOOL_HOMEDIR_H */ diff --git a/src/tool_homedir.c b/src/tool_homedir.c deleted file mode 100644 index 632bdcc4f..000000000 --- a/src/tool_homedir.c +++ /dev/null @@ -1,132 +0,0 @@ -/*************************************************************************** - * _ _ ____ _ - * Project ___| | | | _ \| | - * / __| | | | |_) | | - * | (__| |_| | _ <| |___ - * \___|\___/|_| \_\_____| - * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. - * - * This software is licensed as described in the file COPYING, which - * you should have received as part of this distribution. The terms - * are also available at https://curl.se/docs/copyright.html. - * - * You may opt to use, copy, modify, merge, publish, distribute and/or sell - * copies of the Software, and permit persons to whom the Software is - * furnished to do so, under the terms of the COPYING file. - * - * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY - * KIND, either express or implied. - * - ***************************************************************************/ -#include "tool_setup.h" - -#ifdef HAVE_PWD_H -# undef __NO_NET_API /* required for building for AmigaOS */ -# include <pwd.h> -#endif - -#ifdef HAVE_SYS_STAT_H -#include <sys/stat.h> -#endif -#ifdef HAVE_FCNTL_H -#include <fcntl.h> -#endif - -#include <curl/mprintf.h> - -#include "tool_homedir.h" - -#include "memdebug.h" /* keep this as LAST include */ - -static char *GetEnv(const char *variable) -{ - char *dupe, *env; - - env = curl_getenv(variable); - if(!env) - return NULL; - - dupe = strdup(env); - curl_free(env); - return dupe; -} - -/* return the home directory of the current user as an allocated string */ - -/* - * The original logic found a home dir to use (by checking a range of - * environment variables and last using getpwuid) and returned that for the - * parent to use. - * - * With the XDG_CONFIG_HOME support (added much later than the other), this - * variable is treated differently in order to not ruin existing installations - * even if this environment variable is set. If this variable is set, and a - * file name is set to check, then only if that file name exists in that - * directory will it be returned as a "home directory". - * - * 1. use CURL_HOME if set - * 2. use XDG_CONFIG_HOME if set and fname is present - * 3. use HOME if set - * 4. Non-windows: use getpwuid - * 5. Windows: use APPDATA if set - * 6. Windows: use "USERPROFILE\Application Data" is set - */ - -char *homedir(const char *fname) -{ - char *home; - - home = GetEnv("CURL_HOME"); - if(home) - return home; - - if(fname) { - home = GetEnv("XDG_CONFIG_HOME"); - if(home) { - char *c = curl_maprintf("%s" DIR_CHAR "%s", home, fname); - if(c) { - int fd = open(c, O_RDONLY); - curl_free(c); - if(fd >= 0) { - close(fd); - return home; - } - } - free(home); - } - } - - home = GetEnv("HOME"); - if(home) - return home; - -#if defined(HAVE_GETPWUID) && defined(HAVE_GETEUID) - { - struct passwd *pw = getpwuid(geteuid()); - - if(pw) { - home = pw->pw_dir; - if(home && home[0]) - home = strdup(home); - else - home = NULL; - } - } -#endif /* PWD-stuff */ -#ifdef WIN32 - home = GetEnv("APPDATA"); - if(!home) { - char *env = GetEnv("USERPROFILE"); - if(env) { - char *path = curl_maprintf("%s\\Application Data", env); - if(path) { - home = strdup(path); - curl_free(path); - } - free(env); - } - } -#endif /* WIN32 */ - return home; -} diff --git a/src/tool_operate.c b/src/tool_operate.c index b9183c22a..d648dc054 100644 --- a/src/tool_operate.c +++ b/src/tool_operate.c @@ -63,7 +63,7 @@ #include "tool_filetime.h" #include "tool_getparam.h" #include "tool_helpers.h" -#include "tool_homedir.h" +#include "tool_findfile.h" #include "tool_libinfo.h" #include "tool_main.h" #include "tool_msgs.h" @@ -1716,23 +1716,19 @@ static CURLcode single_transfer(struct GlobalConfig *global, if((use_proto & (CURLPROTO_SCP|CURLPROTO_SFTP)) && !config->insecure_ok) { - char *home = homedir(NULL); - if(home) { - char *file = aprintf("%s/.ssh/known_hosts", home); - if(file) { - /* new in curl 7.19.6 */ - result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, file); - curl_free(file); - if(result == CURLE_UNKNOWN_OPTION) - /* libssh2 version older than 1.1.1 */ - result = CURLE_OK; - } - Curl_safefree(home); + char *known = findfile(".ssh/known_hosts", FALSE); + if(known) { + /* new in curl 7.19.6 */ + result = res_setopt_str(curl, CURLOPT_SSH_KNOWNHOSTS, known); + curl_free(known); + if(result == CURLE_UNKNOWN_OPTION) + /* libssh2 version older than 1.1.1 */ + result = CURLE_OK; if(result) break; } else - warnf(global, "No home dir, couldn't find known_hosts file!"); + warnf(global, "Couldn't find a known_hosts file!"); } if(config->no_body || config->remote_time) { diff --git a/src/tool_paramhlp.c b/src/tool_paramhlp.c index 28a8754f1..8ac6cf53e 100644 --- a/src/tool_paramhlp.c +++ b/src/tool_paramhlp.c @@ -30,7 +30,6 @@ #include "tool_cfgable.h" #include "tool_getparam.h" #include "tool_getpass.h" -#include "tool_homedir.h" #include "tool_msgs.h" #include "tool_paramhlp.h" #include "tool_version.h" diff --git a/src/tool_parsecfg.c b/src/tool_parsecfg.c index d26774faf..ba8ac60e2 100644 --- a/src/tool_parsecfg.c +++ b/src/tool_parsecfg.c @@ -5,7 +5,7 @@ * | (__| |_| | _ <| |___ * \___|\___/|_| \_\_____| * - * Copyright (C) 1998 - 2020, Daniel Stenberg, <daniel@haxx.se>, et al. + * Copyright (C) 1998 - 2021, Daniel Stenberg, <daniel@haxx.se>, et al. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms @@ -28,7 +28,7 @@ #include "tool_cfgable.h" #include "tool_getparam.h" #include "tool_helpers.h" -#include "tool_homedir.h" +#include "tool_findfile.h" #include "tool_msgs.h" #include "tool_parsecfg.h" #include "dynbuf.h" @@ -45,9 +45,9 @@ static const char *unslashquote(const char *line, char *param); static bool my_get_line(FILE *fp, struct curlx_dynbuf *, bool *error); #ifdef WIN32 -static FILE *execpath(const char *filename) +static FILE *execpath(const char *filename, char **pathp) { - char filebuffer[512]; + static char filebuffer[512]; /* Get the filename of our executable. GetModuleFileName is already declared * via inclusions done in setup header file. We assume that we are using * the ASCII version here. @@ -62,8 +62,11 @@ static FILE *execpath(const char *filename) /* If we have enough space, build the RC filename */ remaining = sizeof(filebuffer) - strlen(filebuffer); if(strlen(filename) < remaining - 1) { + FILE *f; msnprintf(lastdirchar, remaining, "%s%s", DIR_CHAR, filename); - return fopen(filebuffer, FOPEN_READTEXT); + *pathp = filebuffer; + f = fopen(filebuffer, FOPEN_READTEXT); + return f; } } } @@ -81,55 +84,37 @@ int parseconfig(const char *filename, struct GlobalConfig *global) int rc = 0; struct OperationConfig *operation = global->last; char *pathalloc = NULL; +#ifdef WIN32 +#define DOTSCORE TRUE /* look for underscore-prefixed name too */ +#else +#define DOTSCORE FALSE +#endif - if(!filename || !*filename) { - /* NULL or no file name attempts to load .curlrc from the homedir! */ - - char *home = homedir(".curlrc"); -#ifndef WIN32 - if(home) { - pathalloc = curl_maprintf("%s%s.curlrc", home, DIR_CHAR); - if(!pathalloc) { - free(home); - return 1; /* out of memory */ + if(!filename) { + /* NULL means load .curlrc from homedir! */ + char *curlrc = findfile(".curlrc", DOTSCORE); + if(curlrc) { + file = fopen(curlrc, FOPEN_READTEXT); + if(!file) { + curl_free(curlrc); + return 1; } - filename = pathalloc; - } -#else /* Windows */ - if(home) { - int i = 0; - char prefix = '.'; - do { - /* if it was allocated in a previous attempt */ - curl_free(pathalloc); - /* check for .curlrc then _curlrc in the home dir */ - pathalloc = curl_maprintf("%s%s%ccurlrc", home, DIR_CHAR, prefix); - if(!pathalloc) { - free(home); - return 1; /* out of memory */ - } - - /* Check if the file exists - if not, try _curlrc */ - file = fopen(pathalloc, FOPEN_READTEXT); - if(file) { - filename = pathalloc; - break; - } - prefix = '_'; - } while(++i < 2); + filename = pathalloc = curlrc; } - if(!filename) { +#ifdef WIN32 /* Windows */ + else { + char *fullp; /* check for .curlrc then _curlrc in the dir of the executable */ - file = execpath(".curlrc"); + file = execpath(".curlrc", &fullp); if(!file) - file = execpath("_curlrc"); + file = execpath("_curlrc", &fullp); + if(file) + /* this is the filename we read from */ + filename = fullp; } #endif - - Curl_safefree(home); /* we've used it, now free it */ } - - if(!file && filename) { /* no need to fopen() again */ + else { if(strcmp(filename, "-")) file = fopen(filename, FOPEN_READTEXT); else @@ -145,6 +130,7 @@ int parseconfig(const char *filename, struct GlobalConfig *global) struct curlx_dynbuf buf; bool fileerror; curlx_dyn_init(&buf, MAX_CONFIG_LINE_LENGTH); + DEBUGASSERT(filename); while(my_get_line(file, &buf, &fileerror)) { int res; |