Sending translation for Finnish
[profile/ivi/pulseaudio.git] / 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 <pulsecore/core-error.h>
40 #include <pulsecore/core-util.h>
41 #include <pulsecore/log.h>
42 #include <pulsecore/random.h>
43 #include <pulsecore/macro.h>
44
45 #include "authkey.h"
46
47 /* Generate a new authorization key, store it in file fd and return it in *data  */
48 static int generate(int fd, void *ret_data, size_t length) {
49     ssize_t r;
50
51     pa_assert(fd >= 0);
52     pa_assert(ret_data);
53     pa_assert(length > 0);
54
55     pa_random(ret_data, length);
56
57     lseek(fd, (off_t) 0, SEEK_SET);
58     (void) ftruncate(fd, (off_t) 0);
59
60     if ((r = pa_loop_write(fd, ret_data, length, NULL)) < 0 || (size_t) r != length) {
61         pa_log("Failed to write cookie file: %s", pa_cstrerror(errno));
62         return -1;
63     }
64
65     return 0;
66 }
67
68 #ifndef O_BINARY
69 #define O_BINARY 0
70 #endif
71
72 #ifndef O_NOCTTY
73 #define O_NOCTTY 0
74 #endif
75
76 /* Load an euthorization cookie from file fn and store it in data. If
77  * the cookie file doesn't exist, create it */
78 static int load(const char *fn, void *data, size_t length) {
79     int fd = -1;
80     int writable = 1;
81     int unlock = 0, ret = -1;
82     ssize_t r;
83
84     pa_assert(fn);
85     pa_assert(data);
86     pa_assert(length > 0);
87
88     if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
89
90         if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY|O_NOCTTY)) < 0) {
91             pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
92             goto finish;
93         } else
94             writable = 0;
95     }
96
97     unlock = pa_lock_fd(fd, 1) >= 0;
98
99     if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
100         pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
101         goto finish;
102     }
103
104     if ((size_t) r != length) {
105         pa_log_debug("Got %d bytes from cookie file '%s', expected %d", (int) r, fn, (int) length);
106
107         if (!writable) {
108             pa_log_warn("Unable to write cookie to read-only file");
109             goto finish;
110         }
111
112         if (generate(fd, data, length) < 0)
113             goto finish;
114     }
115
116     ret = 0;
117
118 finish:
119
120     if (fd >= 0) {
121
122         if (unlock)
123             pa_lock_fd(fd, 0);
124
125         if (pa_close(fd) < 0) {
126             pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
127             ret = -1;
128         }
129     }
130
131     return ret;
132 }
133
134 /* Load a cookie from a cookie file. If the file doesn't exist, create it. */
135 int pa_authkey_load(const char *path, void *data, size_t length) {
136     int ret;
137
138     pa_assert(path);
139     pa_assert(data);
140     pa_assert(length > 0);
141
142     if ((ret = load(path, data, length)) < 0)
143         pa_log_warn("Failed to load authorization key '%s': %s", path, (ret < 0) ? pa_cstrerror(errno) : "File corrupt");
144
145     return ret;
146 }
147
148 /* If the specified file path starts with / return it, otherwise
149  * return path prepended with home directory */
150 static const char *normalize_path(const char *fn, char *s, size_t l) {
151
152     pa_assert(fn);
153     pa_assert(s);
154     pa_assert(l > 0);
155
156 #ifndef OS_IS_WIN32
157     if (fn[0] != '/') {
158 #else
159     if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
160 #endif
161         char homedir[PATH_MAX];
162
163         if (!pa_get_home_dir(homedir, sizeof(homedir)))
164             return NULL;
165
166 #ifndef OS_IS_WIN32
167         pa_snprintf(s, l, "%s/%s", homedir, fn);
168 #else
169         pa_snprintf(s, l, "%s\\%s", homedir, fn);
170 #endif
171         return s;
172     }
173
174     return fn;
175 }
176
177 /* Load a cookie from a file in the home directory. If the specified
178  * path starts with /, use it as absolute path instead. */
179 int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
180     char path[PATH_MAX];
181     const char *p;
182
183     pa_assert(fn);
184     pa_assert(data);
185     pa_assert(length > 0);
186
187     if (!(p = normalize_path(fn, path, sizeof(path))))
188         return -2;
189
190     return pa_authkey_load(p, data, length);
191 }
192
193 /* Store the specified cookie in the speicified 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 path[PATH_MAX];
199     const char *p;
200
201     pa_assert(fn);
202     pa_assert(data);
203     pa_assert(length > 0);
204
205     if (!(p = normalize_path(fn, path, sizeof(path))))
206         return -2;
207
208     if ((fd = open(p, O_RDWR|O_CREAT|O_NOCTTY, S_IRUSR|S_IWUSR)) < 0) {
209         pa_log_warn("Failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
210         goto finish;
211     }
212
213     unlock = pa_lock_fd(fd, 1) >= 0;
214
215     if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
216         pa_log("Failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
217         goto finish;
218     }
219
220     ret = 0;
221
222 finish:
223
224     if (fd >= 0) {
225
226         if (unlock)
227             pa_lock_fd(fd, 0);
228
229         if (pa_close(fd) < 0) {
230             pa_log_warn("Failed to close cookie file: %s", pa_cstrerror(errno));
231             ret = -1;
232         }
233     }
234
235     return ret;
236 }