diff options
author | Werner Koch <wk@gnupg.org> | 2020-10-20 10:43:55 +0200 |
---|---|---|
committer | Werner Koch <wk@gnupg.org> | 2020-10-20 12:15:55 +0200 |
commit | c94ee1386e0d5cdac51086c4d5b92de59c09c9b5 (patch) | |
tree | 34089b99da850a449f95ab9dd7e88317194b5f11 /common | |
parent | gpg,ecc: Fix SOS handling when receiving from agent. (diff) | |
download | gnupg2-c94ee1386e0d5cdac51086c4d5b92de59c09c9b5.tar.xz gnupg2-c94ee1386e0d5cdac51086c4d5b92de59c09c9b5.zip |
Replace all calls to access by gnupg_access
* common/sysutils.c (gnupg_access): New. Replace all calls to access
by this wrapper.
* common/homedir.c (w32_shgetfolderpath): Change to return UTF-8
directory name.
(standard_homedir): Adjust for change.
(w32_commondir, gnupg_cachedir): Ditto.
--
Also use SHGetFolderPathW instead of SHGetFolderPathA on Windows.
This is required to correctly handle non-ascii filenames on Windows.
GnuPG-bug-id: 5098
Diffstat (limited to 'common')
-rw-r--r-- | common/exechelp-posix.c | 5 | ||||
-rw-r--r-- | common/exechelp-w32.c | 5 | ||||
-rw-r--r-- | common/homedir.c | 77 | ||||
-rw-r--r-- | common/sysutils.c | 43 | ||||
-rw-r--r-- | common/sysutils.h | 1 | ||||
-rw-r--r-- | common/t-exectool.c | 1 |
6 files changed, 69 insertions, 63 deletions
diff --git a/common/exechelp-posix.c b/common/exechelp-posix.c index 2b724ce5f..b14410821 100644 --- a/common/exechelp-posix.c +++ b/common/exechelp-posix.c @@ -845,14 +845,15 @@ gpg_error_t gnupg_spawn_process_detached (const char *pgmname, const char *argv[], const char *envp[] ) { + gpg_err_code_t ec; pid_t pid; int i; if (getuid() != geteuid()) return my_error (GPG_ERR_BUG); - if (access (pgmname, X_OK)) - return my_error_from_syserror (); + if ((ec = gnupg_access (pgmname, X_OK))) + return gpg_err_make (default_errsource, ec); pid = fork (); if (pid == (pid_t)(-1)) diff --git a/common/exechelp-w32.c b/common/exechelp-w32.c index be684caaa..a7897cbfc 100644 --- a/common/exechelp-w32.c +++ b/common/exechelp-w32.c @@ -866,13 +866,14 @@ gnupg_spawn_process_detached (const char *pgmname, const char *argv[], int cr_flags; char *cmdline; BOOL in_job = FALSE; + gpg_err_code_t ec; /* We don't use ENVP. */ (void)envp; - if (access (pgmname, X_OK)) - return my_error_from_syserror (); + if ((ec = gnupg_access (pgmname, X_OK))) + return gpg_err_make (default_errsource, ec); /* Prepare security attributes. */ memset (&sec_attr, 0, sizeof sec_attr ); diff --git a/common/homedir.c b/common/homedir.c index f0e5362ba..dd1575cd0 100644 --- a/common/homedir.c +++ b/common/homedir.c @@ -117,14 +117,16 @@ w32_try_mkdir (const char *dir) #endif -/* This is a helper function to load a Windows function from either of - one DLLs. */ +/* This is a helper function to load and call a Windows function from + * either of one DLLs. On success an UTF-8 file name is returned. + * ERRNO is _not_ set on error. */ #ifdef HAVE_W32_SYSTEM -static HRESULT -w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) +static char * +w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d) { static int initialized; - static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPSTR); + static HRESULT (WINAPI * func)(HWND,int,HANDLE,DWORD,LPWSTR); + wchar_t wfname[MAX_PATH]; if (!initialized) { @@ -139,7 +141,7 @@ w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) handle = dlopen (dllnames[i], RTLD_LAZY); if (handle) { - func = dlsym (handle, "SHGetFolderPathA"); + func = dlsym (handle, "SHGetFolderPathW"); if (!func) { dlclose (handle); @@ -149,10 +151,10 @@ w32_shgetfolderpath (HWND a, int b, HANDLE c, DWORD d, LPSTR e) } } - if (func) - return func (a,b,c,d,e); + if (func && func (a,b,c,d,wfname) >= 0) + return wchar_to_utf8 (wfname); else - return -1; + return NULL; } #endif /*HAVE_W32_SYSTEM*/ @@ -248,25 +250,17 @@ standard_homedir (void) } else { - char path[MAX_PATH]; - - /* It might be better to use LOCAL_APPDATA because this is - defined as "non roaming" and thus more likely to be kept - locally. For private keys this is desired. However, - given that many users copy private keys anyway forth and - back, using a system roaming services might be better - than to let them do it manually. A security conscious - user will anyway use the registry entry to have better - control. */ - if (w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, - NULL, 0, path) >= 0) + char *path; + + path = w32_shgetfolderpath (NULL, CSIDL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0); + if (path) { - char *tmp = xmalloc (strlen (path) + 6 +1); - strcpy (stpcpy (tmp, path), "\\gnupg"); - dir = tmp; + dir = xstrconcat (path, "\\gnupg", NULL); + xfree (path); /* Try to create the directory if it does not yet exists. */ - if (access (dir, F_OK)) + if (gnupg_access (dir, F_OK)) w32_try_mkdir (dir); } else @@ -360,10 +354,10 @@ check_portable_app (const char *dir) char *fname; fname = xstrconcat (dir, DIRSEP_S "gpgconf.exe", NULL); - if (!access (fname, F_OK)) + if (!gnupg_access (fname, F_OK)) { strcpy (fname + strlen (fname) - 3, "ctl"); - if (!access (fname, F_OK)) + if (!gnupg_access (fname, F_OK)) { /* gpgconf.ctl file found. Record this fact. */ w32_portable_app = 1; @@ -440,7 +434,7 @@ w32_commondir (void) if (!dir) { const char *rdir; - char path[MAX_PATH]; + char *path; /* Make sure that w32_rootdir has been called so that we are able to check the portable application flag. The common dir @@ -450,19 +444,17 @@ w32_commondir (void) if (w32_portable_app) return rdir; - if (w32_shgetfolderpath (NULL, CSIDL_COMMON_APPDATA, - NULL, 0, path) >= 0) + path = w32_shgetfolderpath (NULL, CSIDL_COMMON_APPDATA, NULL, 0); + if (path) { - char *tmp = xmalloc (strlen (path) + 4 +1); - strcpy (stpcpy (tmp, path), "\\GNU"); - dir = tmp; + dir = xstrconcat (path, "\\GNU", NULL); /* No auto create of the directory. Either the installer or - the admin has to create these directories. */ + * the admin has to create these directories. */ } else { - /* Ooops: Not defined - probably an old Windows version. - Use the installation directory instead. */ + /* Folder not found or defined - probably an old Windows + * version. Use the installation directory instead. */ dir = xstrdup (rdir); } } @@ -903,7 +895,7 @@ gnupg_cachedir (void) } else { - char path[MAX_PATH]; + char *path; const char *s1[] = { "GNU", "cache", "gnupg", NULL }; int s1_len; const char **comp; @@ -912,8 +904,10 @@ gnupg_cachedir (void) for (comp = s1; *comp; comp++) s1_len += 1 + strlen (*comp); - if (w32_shgetfolderpath (NULL, CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, - NULL, 0, path) >= 0) + path = w32_shgetfolderpath (NULL, + CSIDL_LOCAL_APPDATA|CSIDL_FLAG_CREATE, + NULL, 0); + if (path) { char *tmp = xmalloc (strlen (path) + s1_len + 1); char *p; @@ -924,11 +918,12 @@ gnupg_cachedir (void) p = stpcpy (p, "\\"); p = stpcpy (p, *comp); - if (access (tmp, F_OK)) + if (gnupg_access (tmp, F_OK)) w32_try_mkdir (tmp); } dir = tmp; + xfree (path); } else { @@ -1025,7 +1020,7 @@ get_default_pinentry_name (int reset) char *name2; name2 = xstrconcat (names[i].rfnc (), names[i].name, NULL); - if (!access (name2, F_OK)) + if (!gnupg_access (name2, F_OK)) { /* Use that pinentry. */ xfree (name); diff --git a/common/sysutils.c b/common/sysutils.c index 140d1d7be..99bc021f5 100644 --- a/common/sysutils.c +++ b/common/sysutils.c @@ -811,7 +811,7 @@ gnupg_mkdir (const char *name, const char *modestr) int gnupg_chdir (const char *name) { - /* Note that gpgrt_chdir also sets ERRNO in addition to returing an + /* Note that gpgrt_chdir also sets ERRNO in addition to returning an * gpg-error style error code. */ return gpgrt_chdir (name); } @@ -1033,30 +1033,37 @@ gnupg_unsetenv (const char *name) /* Return the current working directory as a malloced string. Return - NULL and sets ERRNo on error. */ + NULL and sets ERRNO on error. */ char * gnupg_getcwd (void) { - char *buffer; - size_t size = 100; + return gpgrt_getcwd (); +} + + +/* A simple wrapper around access. NAME is expected to be utf8 + * encoded. This function returns an error code and sets ERRNO. */ +gpg_err_code_t +gnupg_access (const char *name, int mode) +{ +#if GPGRT_VERSION_NUMBER < 0x012800 /* 1.39 */ +# ifdef HAVE_W32_SYSTEM + wchar_t *wfname; - for (;;) + wfname = utf8_to_wchar (fname); + if (!wfname) + ec = gpg_err_code_from_syserror (); + else { - buffer = xtrymalloc (size+1); - if (!buffer) - return NULL; -#ifdef HAVE_W32CE_SYSTEM - strcpy (buffer, "/"); /* Always "/". */ - return buffer; + ec = _waccess (wfname, mode)? gpg_err_code_from_syserror () : 0; + xfree (wfname); + } +# else + return access (name, mode)? gpg_err_code_from_syserror () : 0; +# endif #else - if (getcwd (buffer, size) == buffer) - return buffer; - xfree (buffer); - if (errno != ERANGE) - return NULL; - size *= 2; + return gpgrt_access (name, mode); #endif - } } diff --git a/common/sysutils.h b/common/sysutils.h index daded986f..12b45e47c 100644 --- a/common/sysutils.h +++ b/common/sysutils.h @@ -73,6 +73,7 @@ char *gnupg_mkdtemp (char *template); int gnupg_setenv (const char *name, const char *value, int overwrite); int gnupg_unsetenv (const char *name); char *gnupg_getcwd (void); +gpg_err_code_t gnupg_access (const char *name, int mode); gpg_error_t gnupg_chuid (const char *user, int silent); char *gnupg_get_socket_name (int fd); int gnupg_fd_valid (int fd); diff --git a/common/t-exectool.c b/common/t-exectool.c index 9cea2d1be..e1fffdcaa 100644 --- a/common/t-exectool.c +++ b/common/t-exectool.c @@ -45,6 +45,7 @@ test_executing_true (void) char *result; size_t len; + /* Fixme: We should use gpgrt_access here. */ if (access (pgmname, X_OK)) { if (access (alt_pgmname, X_OK)) |