]> code.delx.au - pulseaudio/blobdiff - polyp/authkey.c
add POSIX locking to authkey.c
[pulseaudio] / polyp / authkey.c
index 9b60506ffa1a25476ccc93870a94b3d3bbf4bfbc..1e2edb07dbe4a360c54abed75c043b0e8b16af3c 100644 (file)
 
 #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;
-    }
+    assert(fd >= 0 && data && length);
 
-    ret = 0;
-    
-finish:
-    if (fd >= 0)
-        close(fd);
-
-    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;
-        pa_log(__FILE__": 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));
         
@@ -90,41 +65,81 @@ 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\n");
         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;
+    assert(fn && data && length);
+    int unlock = 0, ret;
+    ssize_t r;
+
+    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'\n", fn);
+            goto finish;
+        } else
+            writable = 0;
+    }
+
+    unlock = pa_lock_file(fd, 1) >= 0;
+
+    if ((r = pa_loop_read(fd, data, length)) < 0) {
+        pa_log(__FILE__": failed to read cookie file '%s'\n", fn);
+        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_file(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)
-        pa_log(__FILE__": 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;
 }