]> code.delx.au - pulseaudio/blobdiff - polyp/authkey.c
Make the whole stuff LGPL only
[pulseaudio] / polyp / authkey.c
index 3180b8fd2a382eb8905250679f70a9a1146e6229..05324a61e72b9a19895d752140d68b0d55fad110 100644 (file)
@@ -4,17 +4,17 @@
   This file is part of polypaudio.
  
   polypaudio is free software; you can redistribute it and/or modify
-  it under the terms of the GNU General Public License as published
-  by the Free Software Foundation; either version 2 of the License,
-  or (at your option) any later version.
+  it under the terms of the GNU Lesser General Public License as
+  published by the Free Software Foundation; either version 2.1 of the
+  License, or (at your option) any later version.
  
   polypaudio is distributed in the hope that it will be useful, but
   WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-  General Public License for more details.
+  Lesser General Public License for more details.
  
-  You should have received a copy of the GNU General Public License
-  along with polypaudio; if not, write to the Free Software
+  You should have received a copy of the GNU Lesser General Public
+  License along with polypaudio; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
   USA.
 ***/
 #include <stdlib.h>
 #include <time.h>
 #include <limits.h>
+#include <sys/stat.h>
 
 #include "authkey.h"
 #include "util.h"
+#include "log.h"
 
 #define RANDOM_DEVICE "/dev/urandom"
 
-static int load(const char *fn, void *data, size_t length) {
-    int fd = -1, ret = -1;
+static int generate(int fd, void *data, size_t length) {
+    int random_fd, ret = -1;
     ssize_t r;
-    
-    assert(fn && data && length);
-
-    if ((fd = open(fn, O_RDONLY)) < 0)
-        goto finish;
-
-    if ((r = pa_loop_read(fd, data, length)) < 0 || (size_t) r != length) {
-        ret = -2;
-        goto finish;
-    }
-
-    ret = 0;
-    
-finish:
-    if (fd >= 0)
-        close(fd);
+    assert(fd >= 0 && data && length);
 
-    return ret;
-}
-
-static int generate(const char *fn, void *data, size_t length) {
-    int fd = -1, random_fd = -1, ret = -1;
-    ssize_t r;
-    assert(fn && data && length);
-
-    if ((fd = open(fn, O_WRONLY|O_EXCL|O_CREAT, S_IRUSR | S_IWUSR)) < 0)
-        goto finish;
-    
     if ((random_fd = open(RANDOM_DEVICE, O_RDONLY)) >= 0) {
 
         if ((r = pa_loop_read(random_fd, data, length)) < 0 || (size_t) r != length) {
-            ret = -2;
+            pa_log(__FILE__": failed to read entropy from '%s'\n", RANDOM_DEVICE);
             goto finish;
         }
         
     } else {
         uint8_t *p;
         size_t l;
-        fprintf(stderr, "WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s, falling back to unsecure pseudo RNG.\n", strerror(errno));
+        pa_log(__FILE__": WARNING: Failed to open entropy device '"RANDOM_DEVICE"': %s"
+               ", falling back to unsecure pseudo RNG.\n", strerror(errno));
 
         srandom(time(NULL));
         
@@ -88,57 +65,109 @@ static int generate(const char *fn, void *data, size_t length) {
             *p = (uint8_t) random();
     }
 
+    lseek(fd, 0, SEEK_SET);
+
     if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) {
-        ret =  -2;
+        pa_log(__FILE__": failed to write cookie file: %s\n", strerror(errno));
         goto finish;
     }
 
     ret = 0;
 
 finish:
+
+    if (random_fd >= 0)
+        close(random_fd);
+
+    return ret;
+}
+
+static int load(const char *fn, void *data, size_t length) {
+    int fd = -1;
+    int writable = 1;
+    int unlock = 0, ret;
+    ssize_t r;
+    assert(fn && data && length);
+
+    if ((fd = open(fn, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
+        if (errno != EACCES || (fd = open(fn, O_RDONLY)) < 0) {
+            pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno));
+            goto finish;
+        } else
+            writable = 0;
+    }
+
+    unlock = pa_lock_fd(fd, 1) >= 0;
+
+    if ((r = pa_loop_read(fd, data, length)) < 0) {
+        pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno));
+        goto finish;
+    }
+
+    if ((size_t) r != length) {
+        
+        if (!writable) {
+            pa_log(__FILE__": unable to write cookie to read only file\n");
+            goto finish;
+        }
+        
+        if (generate(fd, data, length) < 0)
+            goto finish;
+    }
+
+    ret = 0;
+    
+finish:
+
     if (fd >= 0) {
-        if (ret != 0)
-            unlink(fn);
+        
+        if (unlock)
+            pa_lock_fd(fd, 0);
+        
         close(fd);
     }
-    if (random_fd >= 0)
-        close(random_fd);
 
     return ret;
 }
 
 int pa_authkey_load(const char *path, void *data, size_t length) {
-    int ret, i;
+    int ret;
 
     assert(path && data && length);
-    
-    for (i = 0; i < 10; i++) {
-        if ((ret = load(path, data, length)) < 0)
-            if (ret == -1 && errno == ENOENT)
-                if ((ret = generate(path,  data, length)) < 0)
-                    if (ret == -1 && errno == EEXIST)
-                        continue;
-        break;
-    }
+
+    ret = load(path, data, length);
 
     if (ret < 0)
-        fprintf(stderr, "Failed to load authorization key '%s': %s\n", path, (ret == -1) ? strerror(errno) : "file corrupt");
+        pa_log(__FILE__": Failed to load authorization key '%s': %s\n", path,
+               (ret == -1) ? strerror(errno) : "file corrupt");
 
     return ret;
 }
 
+static const char *normalize_path(const char *fn, char *s, size_t l) {
+    assert(fn && s && l > 0);
+
+    if (fn[0] != '/') {
+        char homedir[PATH_MAX];
+        if (!pa_get_home_dir(homedir, sizeof(homedir)))
+            return NULL;
+        
+        snprintf(s, l, "%s/%s", homedir, fn);
+        return s;
+    }
+
+    return fn;
+}
+
 int pa_authkey_load_from_home(const char *fn, void *data, size_t length) {
-    char *home;
     char path[PATH_MAX];
-
+    const char *p;
     assert(fn && data && length);
-    
-    if (!(home = getenv("HOME")))
-        return -2;
-    
-    snprintf(path, sizeof(path), "%s/%s", home, fn);
 
-    return pa_authkey_load(path, data, length);
+    if (!(p = normalize_path(fn, path, sizeof(path))))
+        return -2;
+        
+    return pa_authkey_load(p, data, length);
 }
 
 int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
@@ -149,3 +178,41 @@ int pa_authkey_load_auto(const char *fn, void *data, size_t length) {
     else
         return pa_authkey_load_from_home(fn, data, length);
 }
+
+int pa_authkey_save(const char *fn, const void *data, size_t length) {
+    int fd = -1;
+    int unlock = 0, ret = -1;
+    ssize_t r;
+    char path[PATH_MAX];
+    const char *p;
+    assert(fn && data && length);
+
+    if (!(p = normalize_path(fn, path, sizeof(path))))
+        return -2;
+
+    if ((fd = open(p, O_RDWR|O_CREAT, S_IRUSR|S_IWUSR)) < 0) {
+        pa_log(__FILE__": failed to open cookie file '%s': %s\n", fn, strerror(errno));
+        goto finish;
+    }
+
+    unlock = pa_lock_fd(fd, 1) >= 0;
+
+    if ((r = pa_loop_write(fd, data, length)) < 0 || (size_t) r != length) {
+        pa_log(__FILE__": failed to read cookie file '%s': %s\n", fn, strerror(errno));
+        goto finish;
+    }
+
+    ret = 0;
+    
+finish:
+
+    if (fd >= 0) {
+        
+        if (unlock)
+            pa_lock_fd(fd, 0);
+        
+        close(fd);
+    }
+
+    return ret;
+}