2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as
9 published by the Free Software Foundation; either version 2.1 of the
10 License, or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
33 #include <pulse/util.h>
34 #include <pulse/xmalloc.h>
35 #include <pulsecore/core-error.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/log.h>
38 #include <pulsecore/random.h>
39 #include <pulsecore/macro.h>
43 /* Generate a new authentication key, store it in file fd and return it in *data */
44 static int generate(int fd, void *ret_data, size_t length) {
49 pa_assert(length > 0);
51 pa_random(ret_data, length);
53 lseek(fd, (off_t) 0, SEEK_SET);
54 if (ftruncate(fd, (off_t) 0) < 0) {
55 pa_log("Failed to truncate cookie file: %s", pa_cstrerror(errno));
59 if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) {
60 pa_log("Failed to write cookie file: %s", pa_cstrerror(errno));
71 /* Load an authentication cookie from file fn and store it in data. If
72 * the cookie file doesn't exist, create it */
73 static int load(const char *fn, bool create, void *data, size_t length) {
76 int unlock = 0, ret = -1;
81 pa_assert(length > 0);
84 pa_make_secure_parent_dir(fn, pa_in_system_mode() ? 0755U : 0700U, -1, -1, false);
86 if ((fd = pa_open_cloexec(fn, (create ? O_RDWR|O_CREAT : O_RDONLY)|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
88 if (!create || errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) {
89 pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
95 unlock = pa_lock_fd(fd, 1) >= 0;
97 if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
98 pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
102 if ((size_t) r != length) {
103 pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length);
106 pa_log_warn("Unable to write cookie to read-only file");
110 if (generate(fd, data, length) < 0)
123 if (pa_close(fd) < 0) {
124 pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
132 /* If the specified file path starts with / return it, otherwise
133 * return path prepended with the config home directory. */
134 static int normalize_path(const char *fn, char **_r) {
138 if (!pa_is_path_absolute(fn))
139 return pa_append_to_config_home_dir(fn, _r);
141 *_r = pa_xstrdup(fn);
145 int pa_authkey_load(const char *fn, bool create, void *data, size_t length) {
151 pa_assert(length > 0);
153 if ((ret = normalize_path(fn, &p)) < 0)
156 if ((ret = load(p, create, data, length)) < 0)
157 pa_log_warn("Failed to load authentication key '%s': %s", p, (ret < 0) ? pa_cstrerror(errno) : "File corrupt");
164 /* Store the specified cookie in the specified cookie file */
165 int pa_authkey_save(const char *fn, const void *data, size_t length) {
173 pa_assert(length > 0);
175 if ((ret = normalize_path(fn, &p)) < 0)
178 if ((fd = pa_open_cloexec(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
179 pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
184 unlock = pa_lock_fd(fd, 1) >= 0;
186 if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
187 pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
199 if (pa_close(fd) < 0) {
200 pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));