Add copyright notices to all relevant files. (based on svn log)
[profile/ivi/pulseaudio.git] / src / pulsecore / authkey.c
1 /* $Id$ */
2
3 /***
4   This file is part of PulseAudio.
5
6   Copyright 2004-2006 Lennart Poettering
7   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
8
9   PulseAudio is free software; you can redistribute it and/or modify
10   it under the terms of the GNU Lesser General Public License as
11   published by the Free Software Foundation; either version 2.1 of the
12   License, or (at your option) any later version.
13
14   PulseAudio is distributed in the hope that it will be useful, but
15   WITHOUT ANY WARRANTY; without even the implied warranty of
16   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17   Lesser General Public License for more details.
18
19   You should have received a copy of the GNU Lesser General Public
20   License along with PulseAudio; if not, write to the Free Software
21   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
22   USA.
23 ***/
24
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28
29 #include <assert.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <string.h>
33 #include <errno.h>
34 #include <stdio.h>
35 #include <inttypes.h>
36 #include <stdlib.h>
37 #include <time.h>
38 #include <limits.h>
39 #include <sys/stat.h>
40
41 #include <pulse/util.h>
42 #include <pulsecore/core-error.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/random.h>
46
47 #include "authkey.h"
48
49 /* Generate a new authorization key, store it in file fd and return it in *data  */
50 static int generate(int fd, void *ret_data, size_t length) {
51     ssize_t r;
52     assert(fd >= 0 && ret_data && length);
53
54     pa_random(ret_data, length);
55
56     lseek(fd, 0, SEEK_SET);
57     ftruncate(fd, 0);
58
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));
61         return -1;
62     }
63
64     return 0;
65 }
66
67 #ifndef O_BINARY
68 #define O_BINARY 0
69 #endif
70
71 /* Load an euthorization 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, void *data, size_t length) {
74     int fd = -1;
75     int writable = 1;
76     int unlock = 0, ret = -1;
77     ssize_t r;
78     assert(fn && data && length);
79
80     if ((fd = open(fn, O_RDWR|O_CREAT|O_BINARY, S_IRUSR|S_IWUSR)) < 0) {
81         if (errno != EACCES || (fd = open(fn, O_RDONLY|O_BINARY)) < 0) {
82             pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
83             goto finish;
84         } else
85             writable = 0;
86     }
87
88     unlock = pa_lock_fd(fd, 1) >= 0;
89
90     if ((r = pa_loop_read(fd, data, length, NULL)) < 0) {
91         pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
92         goto finish;
93     }
94
95     if ((size_t) r != length) {
96         pa_log_debug("got %d bytes from cookie file '%s', expected %d", (int)r, fn, (int)length);
97
98         if (!writable) {
99             pa_log("unable to write cookie to read only file");
100             goto finish;
101         }
102
103         if (generate(fd, data, length) < 0)
104             goto finish;
105     }
106
107     ret = 0;
108
109 finish:
110
111     if (fd >= 0) {
112
113         if (unlock)
114             pa_lock_fd(fd, 0);
115
116         close(fd);
117     }
118
119     return ret;
120 }
121
122 /* Load a cookie from a cookie file. If the file doesn't exist, create it. */
123 int pa_authkey_load(const char *path, void *data, size_t length) {
124     int ret;
125
126     assert(path && data && length);
127
128     ret = load(path, data, length);
129
130     if (ret < 0)
131         pa_log("Failed to load authorization key '%s': %s", path,
132                (ret == -1) ? pa_cstrerror(errno) : "file corrupt");
133
134     return ret;
135 }
136
137 /* If the specified file path starts with / return it, otherwise
138  * return path prepended with home directory */
139 static const char *normalize_path(const char *fn, char *s, size_t l) {
140     assert(fn && s && l > 0);
141
142 #ifndef OS_IS_WIN32
143     if (fn[0] != '/') {
144 #else
145     if (strlen(fn) < 3 || !isalpha(fn[0]) || fn[1] != ':' || fn[2] != '\\') {
146 #endif
147         char homedir[PATH_MAX];
148         if (!pa_get_home_dir(homedir, sizeof(homedir)))
149             return NULL;
150
151 #ifndef OS_IS_WIN32
152         snprintf(s, l, "%s/%s", homedir, fn);
153 #else
154         snprintf(s, l, "%s\\%s", homedir, fn);
155 #endif
156         return s;
157     }
158
159     return fn;
160 }
161
162 /* Load a cookie from a file in the home directory. If the specified
163  * path starts with /, use it as absolute path instead. */
164 int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
165     char path[PATH_MAX];
166     const char *p;
167     assert(fn && data && length);
168
169     if (!(p = normalize_path(fn, path, sizeof(path))))
170         return -2;
171
172     return pa_authkey_load(p, data, length);
173 }
174
175 /* Store the specified cookie in the speicified cookie file */
176 int pa_authkey_save(const char *fn, const void *data, size_t length) {
177     int fd = -1;
178     int unlock = 0, ret = -1;
179     ssize_t r;
180     char path[PATH_MAX];
181     const char *p;
182     assert(fn && data && length);
183
184     if (!(p = normalize_path(fn, path, sizeof(path))))
185         return -2;
186
187     if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
188         pa_log("failed to open cookie file '%s': %s", fn, pa_cstrerror(errno));
189         goto finish;
190     }
191
192     unlock = pa_lock_fd(fd, 1) >= 0;
193
194     if ((r = pa_loop_write(fd, data, length, NULL)) < 0 || (size_t) r != length) {
195         pa_log("failed to read cookie file '%s': %s", fn, pa_cstrerror(errno));
196         goto finish;
197     }
198
199     ret = 0;
200
201 finish:
202
203     if (fd >= 0) {
204
205         if (unlock)
206             pa_lock_fd(fd, 0);
207
208         close(fd);
209     }
210
211     return ret;
212 }