diff options
author | Daiki Ueno <dueno@redhat.com> | 2018-02-27 14:56:33 +0100 |
---|---|---|
committer | Daiki Ueno <ueno@gnu.org> | 2018-02-27 16:33:59 +0100 |
commit | 44c67d90b0448888c784e661b5967204f5b0d47d (patch) | |
tree | c0d838df1c6b93d7e89af0918229049743af6459 /common | |
parent | d8acebf175d727a3e146956fb362c30e7fdec9df (diff) |
common, client: Move runtime directory detection to libp11-common
Diffstat (limited to 'common')
-rw-r--r-- | common/Makefile.am | 5 | ||||
-rw-r--r-- | common/runtime.c | 111 | ||||
-rw-r--r-- | common/runtime.h | 42 | ||||
-rw-r--r-- | common/test-runtime.c | 132 |
4 files changed, 290 insertions, 0 deletions
diff --git a/common/Makefile.am b/common/Makefile.am index d5af029..d67028a 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -28,6 +28,7 @@ libp11_common_la_SOURCES = \ common/message.c common/message.h \ common/path.c common/path.h \ common/pkcs11.h common/pkcs11x.h common/pkcs11i.h \ + common/runtime.c common/runtime.h \ common/url.c common/url.h \ $(NULL) @@ -71,6 +72,7 @@ c_tests += \ test-lexer \ test-message \ test-argv \ + test-runtime \ $(NULL) test_argv_SOURCES = common/test-argv.c @@ -112,6 +114,9 @@ test_tests_LDADD = $(common_LIBS) test_url_SOURCES = common/test-url.c test_url_LDADD = $(common_LIBS) +test_runtime_SOURCES = common/test-runtime.c +test_runtime_LDADD = $(common_LIBS) + check_PROGRAMS += \ frob-getauxval \ frob-getenv \ diff --git a/common/runtime.c b/common/runtime.c new file mode 100644 index 0000000..f713e7d --- /dev/null +++ b/common/runtime.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2018 Red Hat Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Daiki Ueno + */ + +#include "config.h" + +#include "runtime.h" + +#include "compat.h" +#include <pwd.h> +#include <stdio.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <unistd.h> + +static const char * const _p11_runtime_bases_default[] = { "/run", "/var/run", NULL }; +const char * const *_p11_runtime_bases = _p11_runtime_bases_default; + +CK_RV +p11_get_runtime_directory (char **directoryp) +{ + const char *envvar; + const char * const *bases = _p11_runtime_bases; + char prefix[13 + 1 + 20 + 6 + 1]; + char *directory; + uid_t uid; + struct stat sb; + struct passwd pwbuf, *pw; + char buf[1024]; + int i; + + /* We can't always assume the XDG_RUNTIME_DIR envvar here, + * because the PKCS#11 module can be loaded by a program that + * calls setuid(). */ + envvar = secure_getenv ("XDG_RUNTIME_DIR"); + + if (envvar != NULL && envvar[0] != '\0') { + directory = strdup (envvar); + if (!directory) + return CKR_HOST_MEMORY; + + *directoryp = directory; + return CKR_OK; + } + + uid = getuid (); + + for (i = 0; bases[i] != NULL; i++) { + snprintf (prefix, sizeof prefix, "%s/user/%u", + bases[i], (unsigned int) uid); + if (stat (prefix, &sb) != -1 && S_ISDIR (sb.st_mode)) { + directory = strdup (prefix); + if (!directory) + return CKR_HOST_MEMORY; + *directoryp = directory; + return CKR_OK; + } + } + + /* We can't use /run/user/<UID>, fallback to ~/.cache. */ + envvar = secure_getenv ("XDG_CACHE_HOME"); + + if (envvar != NULL && envvar[0] != '\0') { + directory = strdup (envvar); + if (!directory) + return CKR_HOST_MEMORY; + + *directoryp = directory; + return CKR_OK; + } + + if (getpwuid_r (uid, &pwbuf, buf, sizeof buf, &pw) < 0 || + pw == NULL || pw->pw_dir == NULL || *pw->pw_dir != '/') + return CKR_GENERAL_ERROR; + + if (asprintf (&directory, "%s/.cache", pw->pw_dir) < 0) + return CKR_HOST_MEMORY; + *directoryp = directory; + return CKR_OK; +} diff --git a/common/runtime.h b/common/runtime.h new file mode 100644 index 0000000..42b2237 --- /dev/null +++ b/common/runtime.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018 Red Hat Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Daiki Ueno + */ + +#ifndef __RUNTIME_H__ +#define __RUNTIME_H__ + +#include "pkcs11.h" + +CK_RV p11_get_runtime_directory (char **directoryp); + +#endif /* __RUNTIME_H__ */ diff --git a/common/test-runtime.c b/common/test-runtime.c new file mode 100644 index 0000000..294a7ad --- /dev/null +++ b/common/test-runtime.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2018 Red Hat Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Daiki Ueno + */ + +#include "config.h" +#include "test.h" + +#include "runtime.h" +#include "compat.h" + +#include <stdio.h> +#include <stdlib.h> + +static struct { + char *directory; +} test; + +extern const char * const *_p11_runtime_bases; + +static void +setup (void *unused) +{ + test.directory = p11_test_directory ("p11-test-runtime"); +} + +static void +teardown (void *unused) +{ + p11_test_directory_delete (test.directory); + free (test.directory); +} + +static void +test_xdg_runtime_dir (void) +{ + char *directory; + + setenv ("XDG_RUNTIME_DIR", "/nowhere", 1); + p11_get_runtime_directory (&directory); + assert_str_eq ("/nowhere", directory); + free (directory); +} + +static void +test_bases (void) +{ + char *directory; + const char * bases[] = { + NULL, + NULL + }; + char *user, *path; + + if (asprintf (&user, "%s/user", test.directory) < 0) + assert_not_reached (); + if (mkdir (user, 0700) < 0) + assert_not_reached (); + if (asprintf (&path, "%s/%d", user, getuid ()) < 0) + assert_not_reached (); + free (user); + if (mkdir (path, 0700) < 0) + assert_not_reached (); + free (path); + + bases[0] = test.directory; + _p11_runtime_bases = bases; + + unsetenv ("XDG_RUNTIME_DIR"); + p11_get_runtime_directory (&directory); + if (asprintf (&path, "%s/user/%d", test.directory, getuid ()) < 0) + assert_not_reached (); + assert_str_eq (path, directory); + free (path); + free (directory); +} + +static void +test_xdg_cache_home (void) +{ + char *directory; + const char * bases[] = { + NULL + }; + _p11_runtime_bases = bases; + + unsetenv ("XDG_RUNTIME_DIR"); + setenv ("XDG_CACHE_HOME", "/cache", 1); + p11_get_runtime_directory (&directory); + assert_str_eq ("/cache", directory); + free (directory); +} + +int +main (int argc, + char *argv[]) +{ + p11_fixture (setup, teardown); + p11_test (test_xdg_runtime_dir, "/runtime/xdg-runtime-dir"); + p11_test (test_bases, "/runtime/bases"); + p11_test (test_xdg_cache_home, "/runtime/xdg-cache-home"); + p11_test_run (argc, argv); +} |