chiark / gitweb /
disorder authorize now creates ~USER/.disorder/passwd instead of
authorRichard Kettlewell <richard@fanticule>
Tue, 1 Jan 2008 14:21:10 +0000 (14:21 +0000)
committerRichard Kettlewell <richard@fanticule>
Tue, 1 Jan 2008 14:21:10 +0000 (14:21 +0000)
/etc/disorder/config.USER.  This is a bit fiddlier than the old code
but reduces the number of places the user must look for their
password.

Generated passwords are base64 rather than hex, and are slightly
longer (in terms of the underlying bytes).  They aren't human
memorable but in practice they are expected to be kept in
~/.disorder/passwd or a browser's password store.

The configuration parser now always uses pw_home rather than $HOME to
find ~/.disorder.

Mention Ubuntu in README as the debs work there too.

README
clients/authorize.c
doc/disorder.1.in
doc/disorder_config.5.in
lib/configuration.c

diff --git a/README b/README
index 11bbbb047f70d0c1e0ce8eba1f65b852f11d5e94..1c5edde5cd860d57e1553880569f3d31c48143a1 100644 (file)
--- a/README
+++ b/README
@@ -8,12 +8,13 @@ DisOrder is a multi-user software jukebox.
    * It supports both ALSA and OSS and can also broadcast an RTP stream over a
      LAN; a player for the latter is included.
    * Tracks may be selected either via a hierarchical interface or by a fast
-     word search.
+     word or tag search.
    * It has a web interface (allowing access from graphical web browsers) and a
      GTK+ interface that runs on Linux and Mac systems.
    * Playing tracks can be paused or cancelled ("scratched").
 
-See CHANGES for details of recent changes to DisOrder.
+See CHANGES for details of recent changes to DisOrder and README.upgrades for
+upgrade instructions.
 
 The server supports Linux and can be made to work on a Mac (see README.mac).
 The clients work on both Linux and the Mac.  It could probably be ported to
@@ -71,10 +72,11 @@ Installation
    "This place'd be a paradise tomorrow, if every department had a supervisor
    with a machine-gun"
 
-NOTE: If you are upgrading from an earlier version, see README.upgrades.
+IMPORTANT: If you are upgrading from an earlier version, see README.upgrades.
 
-On a Debian system, if you install from .deb files then you should be able to
-skip steps 1 to 6 and configure it via debconf.  This is strongly recommended!
+On a Debian or Ubuntu system, if you install from .deb files then you should be
+able to skip steps 1 to 6 and configure it via debconf.  This is strongly
+recommended!
 
 1. Build the software.  Do something like this:
 
@@ -164,7 +166,7 @@ skip steps 1 to 6 and configure it via debconf.  This is strongly recommended!
      disorder authorize USERNAME
 
    This will automatically choose a random password and create
-   /etc/disorder/config.USERNAME.
+   ~USERNAME/.disorder/passwd.
 
    Those users should now be able to access the server from the same host as it
    runs on, either via the disorder command or Disobedience.  To run
index c442d23730b55f4b3b28a4bc103fce00e2aff982..fb88c68be919a2a9cdf59a1006cc2c42b9dddca9 100644 (file)
@@ -34,7 +34,7 @@
 #include "log.h"
 #include "configuration.h"
 #include "printf.h"
-#include "hex.h"
+#include "base64.h"
 
 /** @brief Create a DisOrder login for the calling user, called @p user
  * @param client DisOrder client
  * @return 0 on success, non-0 on error
  */
 int authorize(disorder_client *client, const char *user, const char *rights) {
-  uint8_t pwbin[10];
-  const struct passwd *pw, *jbpw;
-  gid_t jbgid;
-  char *c, *t, *pwhex;
+  /* base64 is 3-into-4 so we make the password a multiple of 3 bytes long */
+  uint8_t pwbin[12];
+  const struct passwd *pw;
+  char *pwhex;
   int fd;
   FILE *fp;
+  char *configdir, *configpath, *configpathtmp;
+  struct stat sb;
+  uid_t old_uid = getuid();
+  gid_t old_gid = getgid();
 
-  if(!(jbpw = getpwnam(config->user)))
-    fatal(0, "cannot find user %s", config->user);
-  jbgid = jbpw->pw_gid;
   if(!(pw = getpwnam(user)))
-    fatal(0, "no such user as %s", user);
-  if((c = config_userconf(0, pw)) && access(c, F_OK) == 0) {
-    error(0, "%s already exists", c);
-    return -1;
-  }
-  if((c = config_usersysconf(pw)) && access(c, F_OK) == 0) {
-    error(0, "%s already exists", c);
+    /* If it's a NIS world then /etc/passwd may be a lie, but it emphasizes
+     * that it's talking about the login user, not the DisOrder user */
+    fatal(0, "no such user as %s in /etc/passwd", user);
+
+  /* Choose a random password */
+  gcry_randomize(pwbin, sizeof pwbin, GCRY_STRONG_RANDOM);
+  pwhex = mime_to_base64(pwbin, sizeof pwbin);
+
+  /* Create the user on the server */
+  if(disorder_adduser(client, user, pwhex, rights))
     return -1;
+
+  /* Become the target user */
+  if(setegid(pw->pw_gid) < 0)
+    fatal(errno, "setegid %lu", (unsigned long)pw->pw_gid);
+  if(seteuid(pw->pw_uid) < 0)
+    fatal(errno, "seteuid %lu", (unsigned long)pw->pw_uid);
+  
+  /* Make sure the configuration directory exists*/
+  byte_xasprintf(&configdir, "%s/.disorder", pw->pw_dir);
+  if(mkdir(configdir, 02700) < 0) {
+    if(errno != EEXIST)
+      fatal(errno, "creating %s", configdir);
   }
-  byte_xasprintf(&t, "%s.new", c);
-  gcry_randomize(pwbin, sizeof pwbin, GCRY_STRONG_RANDOM);
-  pwhex = hex(pwbin, sizeof pwbin);
 
-  /* create config.USER, to end up with mode 400 user:<anything> */
-  if((fd = open(t, O_WRONLY|O_CREAT|O_EXCL, 0600)) < 0)
-    fatal(errno, "error creating %s", t);
-  if(fchown(fd, pw->pw_uid, -1) < 0)
-    fatal(errno, "error chowning %s", t);
-  if(fchmod(fd, 0400) < 0)
-    fatal(errno, "error chmoding %s", t);
+  /* Make sure the configuration file does not exist */
+  byte_xasprintf(&configpath, "%s/passwd", configdir);
+  if(lstat(configpath, &sb) == 0)
+    fatal(0, "%s already exists", configpath);
+  if(errno != ENOENT)
+    fatal(errno, " checking %s", configpath);
+  
+  byte_xasprintf(&configpathtmp, "%s.new", configpath);
+
+  /* Create config file with mode 600 */
+  if((fd = open(configpathtmp, O_WRONLY|O_CREAT, 0600)) < 0)
+    fatal(errno, "error creating %s", configpathtmp);
+
+  /* Write password */
   if(!(fp = fdopen(fd, "w")))
     fatal(errno, "error calling fdopen");
   if(fprintf(fp, "password %s\n", pwhex) < 0
      || fclose(fp) < 0)
-    fatal(errno, "error writing to %s", t);
-  if(rename(t, c) < 0)
-    fatal(errno, "error renaming %s to %s", t, c);
+    fatal(errno, "error writing to %s", configpathtmp);
 
-  /* create the user on the server */
-  if(disorder_adduser(client, user, pwhex, rights))
-    return -1;
+  /* Rename config file into place */
+  if(rename(configpathtmp, configpath) < 0)
+    fatal(errno, "error renaming %s to %s", configpathtmp, configpath);
 
+  /* Put our identity back */
+  if(seteuid(old_uid) < 0)
+    fatal(errno, "seteuid %lu", (unsigned long)old_uid);
+  if(setegid(old_gid) < 0)
+    fatal(errno, "setegid %lu", (unsigned long)old_gid);
+  
   return 0;
 }
 
index 1fd94b5bda449993e1e59a7b64d6338497f1e22f..7a443b76408f2a880834130ab4ad228e37147999 100644 (file)
@@ -63,8 +63,12 @@ Create \fIUSER\fR with a random password.  \fIUSER\fR must be a UNIX login
 user (not just any old string).  If \fIRIGHTS\fR is not specified then the
 \fBdefault_rights\fR setting from the server's configuration file applies.
 .IP
-An appropriate \fIconfig.USER\fR is created, owned by the user, so they should
-be able to log in immediately.
+\fI~USER/.disorder/passwd\fR is created with the password in it, so the new
+user should be able to log in immediately.
+.IP
+If writing the \fIpasswd\fR file fails then the user will already have been
+created in DisOrder's user database.  Use \fBdisorder deluser\fR to remove them
+before trying again.
 .TP
 .B deluser \fIUSER\fR
 Delete a user.
index 3b2e5a982e29ec3a2c988a5f58f271f1954cc005..b545b69c1bdf68b1dc2915c24a3d9e0007603a6e 100644 (file)
@@ -200,17 +200,20 @@ Configuration files are read in the following order:
 .TP
 .I pkgconfdir/config.private
 Should be readable only by the jukebox group.  Not really useful any more and
-may be abolished in future.
-.TP
-.I pkgconfdir/config.\fRUSER
-Per-user system-controlled client configuration.  Optional but if it
-exists must be readable only by the relevant user.  Would normally
-contain a \fBpassword\fR directive.
+will be abolished in future.
 .TP
 .I ~\fRUSER\fI/.disorder/passwd
 Per-user client configuration.  Optional but if it exists must be
 readable only by the relevant user.  Would normally contain a
 \fBpassword\fR directive.
+.TP
+.I pkgconfdir/config.\fRUSER
+Per-user system-controlled client configuration.  Optional but if it
+exists must be readable only by the relevant user.  Would normally
+contain a \fBpassword\fR directive.
+.IP
+The prefererred location for per-user passwords is \fI~/.disorder/passwd\fR and
+\fBdisorder authorize\fR writes there now.  
 .SS "Global Configuration"
 .TP
 .B home \fIDIRECTORY\fR
index d81b09b0d63841d2a681287b07011e6bb76549c1..ba50f3cbaa2a3414e2242b1086420e06e478b960 100644 (file)
@@ -1359,7 +1359,7 @@ int config_read(int server) {
       return -1;
     xfree(privconf);
     /* if we have a password file, read it */
-    if((privconf = config_userconf(getenv("HOME"), pw))
+    if((privconf = config_userconf(0, pw))
        && access(privconf, F_OK) == 0
        && config_include(c, privconf))
       return -1;