]> code.delx.au - pulseaudio/blob - src/pulsecore/authkey.c
Merge branch 'master' of git://0pointer.de/pulseaudio
[pulseaudio] / src / pulsecore / authkey.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <unistd.h>
28 #include <fcntl.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <stdio.h>
32 #include <inttypes.h>
33 #include <stdlib.h>
34 #include <time.h>
35 #include <limits.h>
36 #include <sys/stat.h>
37
38 #include <pulse/util.h>
39 #include <pulse/xmalloc.h>
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/log.h>
43 #include <pulsecore/random.h>
44 #include <pulsecore/macro.h>
45
46 #include "authkey.h"
47
48 /* Generate a new authorization key, store it in file fd and return it in *data */
49 static int generate(int fd, void *ret_data, size_t length) {
50 ssize_t r;
51
52 pa_assert(fd >= 0);
53 pa_assert(ret_data);
54 pa_assert(length > 0);
55
56 pa_random(ret_data, length);
57
58 lseek(fd, (off_t) 0, SEEK_SET);
59 (void) ftruncate(fd, (off_t) 0);
60
61 if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) {
62 pa_log("Failed to write cookie file: %s", pa_cstrerror(errno));
63 return -1;
64 }
65
66 return 0;
67 }
68
69 #ifndef O_BINARY
70 #define O_BINARY 0
71 #endif
72
73 #ifndef O_NOCTTY
74 #define O_NOCTTY 0
75 #endif
76
77 /* Load an euthorization cookie from file fn and store it in data. If
78 * the cookie file doesn't exist, create it */
79 static int load(const char *fn, void *data, size_t length) {
80 int fd = -1;
81 int writable = 1;
82 int unlock = 0, ret = -1;
83 ssize_t r;
84
85 pa_assert(fn);
86 pa_assert(data);
87 pa_assert(length > 0);
88
89 if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
90
91 if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) {
92 pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
93 goto finish;
94 } else
95 writable = 0;
96 }
97
98 unlock = pa_lock_fd(fd, 1) >= 0;
99
100 if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
101 pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
102 goto finish;
103 }
104
105 if ((size_t) r != length) {
106 pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length);
107
108 if (!writable) {
109 pa_log_warn("Unable to write cookie to read-only file");
110 goto finish;
111 }
112
113 if (generate(fd, data, length) < 0)
114 goto finish;
115 }
116
117 ret = 0;
118
119 finish:
120
121 if (fd >= 0) {
122
123 if (unlock)
124 pa_lock_fd(fd, 0);
125
126 if (pa_close(fd) < 0) {
127 pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
128 ret = -1;
129 }
130 }
131
132 return ret;
133 }
134
135 /* Load a cookie from a cookie file. If the file doesn't exist, create it. */
136 int pa_authkey_load(const char *path, void *data, size_t length) {
137 int ret;
138
139 pa_assert(path);
140 pa_assert(data);
141 pa_assert(length > 0);
142
143 if ((ret = load(path, data, length)) < 0)
144 pa_log_warn("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt");
145
146 return ret;
147 }
148
149 /* If the specified file path starts with / return it, otherwise
150 * return path prepended with home directory */
151 static char *normalize_path(const char *fn) {
152
153 pa_assert(fn);
154
155 #ifndef OS_IS_WIN32
156 if (fn[0] != '/') {
157 #else
158 if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
159 #endif
160 char *homedir, *s;
161
162 if (!(homedir = pa_get_home_dir_malloc()))
163 return NULL;
164
165 s = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", homedir, fn);
166 pa_xfree(homedir);
167
168 return s;
169 }
170
171 return pa_xstrdup(fn);
172 }
173
174 /* Load a cookie from a file in the home directory. If the specified
175 * path starts with /, use it as absolute path instead. */
176 int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
177 char *p;
178 int ret;
179
180 pa_assert(fn);
181 pa_assert(data);
182 pa_assert(length > 0);
183
184 if (!(p = normalize_path(fn)))
185 return -2;
186
187 ret = pa_authkey_load(p, data, length);
188 pa_xfree(p);
189
190 return ret;
191 }
192
193 /* Store the specified cookie in the specified cookie file */
194 int pa_authkey_save(const char *fn, const void *data, size_t length) {
195 int fd = -1;
196 int unlock = 0, ret = -1;
197 ssize_t r;
198 char *p;
199
200 pa_assert(fn);
201 pa_assert(data);
202 pa_assert(length > 0);
203
204 if (!(p = normalize_path(fn)))
205 return -2;
206
207 if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
208 pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
209 goto finish;
210 }
211
212 unlock = pa_lock_fd(fd, 1) >= 0;
213
214 if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
215 pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
216 goto finish;
217 }
218
219 ret = 0;
220
221 finish:
222
223 if (fd >= 0) {
224
225 if (unlock)
226 pa_lock_fd(fd, 0);
227
228 if (pa_close(fd) < 0) {
229 pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
230 ret = -1;
231 }
232 }
233
234 pa_xfree(p);
235
236 return ret;
237 }