chiark / gitweb /
default_rights directive
authorRichard Kettlewell <rjk@greenend.org.uk>
Fri, 21 Dec 2007 16:23:27 +0000 (16:23 +0000)
committerRichard Kettlewell <rjk@greenend.org.uk>
Fri, 21 Dec 2007 16:23:27 +0000 (16:23 +0000)
README.upgrades
doc/disorder_config.5.in
lib/configuration.c
lib/configuration.h
lib/rights.c
lib/rights.h
lib/trackdb.c
server/server.c
tests/dtest.py
tests/dump.py
tests/user-upgrade.py

index 5bea1cdaf642f9cb191bee6577841ebb6ab00cab..b47022e5510c040d2f0797e4215a0d61b2d4450d 100644 (file)
@@ -21,9 +21,16 @@ all 1.1.x versions.
 Users are now stored in the database rather than in 'allow' directives in a
 private configuration file.  'allow' is still understood in this version, but
 is only used to populate the database on startup.  After the first (successful)
 Users are now stored in the database rather than in 'allow' directives in a
 private configuration file.  'allow' is still understood in this version, but
 is only used to populate the database on startup.  After the first (successful)
-run of the server the remaining 'allow' directives can be deleted.
+run of the server the remaining 'allow' directives should be deleted.
 
 
-'allow' will stop working entirely in a future version.
+'restrict' and 'trust' are replaced by a system of per-user rights.  The
+default user rights are based on the 'restrict' setting, and the rights of
+users created frow 'allow' directives preserve the meaning of 'trust', but
+after the first run you should remove these directives and (optionally) add a
+'default_rights' directive.
+
+'allow', 'restrict' and 'trust' will stop working entirely in a future version
+but for now they will generate harmless error messages.
 
 * 1.4/1.5 -> 2.0
 
 
 * 1.4/1.5 -> 2.0
 
index a90d029a737f8b98ea141d434aba89db2e62b837..25bc90471060c687adcb92a226cb478a2583f253 100644 (file)
@@ -300,6 +300,15 @@ Examples might be \fBiso-8859-1\fR or \fButf-8\fR.
 \fIROOT\fR is the root in the filesystem of the filenames and is
 passed to the plugin module.
 .TP
 \fIROOT\fR is the root in the filesystem of the filenames and is
 passed to the plugin module.
 .TP
+.B default_rights \fIRIGHTS\fR
+Defines the set of rights given to new users.  The argument is a
+comma-separated list of rights.  For the possible values see
+.B "Users And Access Control"
+above.
+.IP
+The default is to allow everything except \fBadmin\fR and \fBregister\fR
+(modified in legacy configurations by the obsolete \fBrestrict\fR directive).
+.TP
 .B device \fINAME\fR
 ALSA device to play raw-format audio.  Default is \fBdefault\fR, i.e. to use
 the whatever the ALSA configured default is.
 .B device \fINAME\fR
 ALSA device to play raw-format audio.  Default is \fBdefault\fR, i.e. to use
 the whatever the ALSA configured default is.
index 3ddfea16e0cd6b4b5d99988fd445314ad9d8fa42..0f1dc96c016b4ffb545a5b79a0d47e9ab2385f19 100644 (file)
@@ -39,6 +39,7 @@
 #include <pcre.h>
 #include <signal.h>
 
 #include <pcre.h>
 #include <signal.h>
 
+#include "rights.h"
 #include "configuration.h"
 #include "mem.h"
 #include "log.h"
 #include "configuration.h"
 #include "mem.h"
 #include "log.h"
@@ -489,6 +490,25 @@ static int set_backend(const struct config_state *cs,
   return 0;
 }
 
   return 0;
 }
 
+static int set_rights(const struct config_state *cs,
+                     const struct conf *whoami,
+                     int nvec, char **vec) {
+  rights_type r;
+
+  if(nvec != 1) {
+    error(0, "%s:%d: '%s' requires one argument",
+         cs->path, cs->line, whoami->name);
+    return -1;
+  }
+  if(parse_rights(vec[0], &r)) {
+    error(0, "%s:%d: invalid rights string '%s'",
+         cs->path, cs->line, vec[0]);
+    return -1;
+  }
+  *ADDRESS(cs->config, rights_type) = r;
+  return 0;
+}
+
 /* free functions */
 
 static void free_none(struct config attribute((unused)) *c,
 /* free functions */
 
 static void free_none(struct config attribute((unused)) *c,
@@ -587,6 +607,7 @@ static const struct conftype
   type_restrict = { set_restrict, free_none },
   type_namepart = { set_namepart, free_namepartlist },
   type_transform = { set_transform, free_transformlist },
   type_restrict = { set_restrict, free_none },
   type_namepart = { set_namepart, free_namepartlist },
   type_transform = { set_transform, free_transformlist },
+  type_rights = { set_rights, free_none },
   type_backend = { set_backend, free_none };
 
 /* specific validation routine */
   type_backend = { set_backend, free_none };
 
 /* specific validation routine */
@@ -902,6 +923,7 @@ static const struct conf conf[] = {
   { C(cookie_login_lifetime),  &type_integer,    validate_positive },
   { C(cookie_key_lifetime),  &type_integer,      validate_positive },
   { C(dbversion),        &type_integer,          validate_positive },
   { C(cookie_login_lifetime),  &type_integer,    validate_positive },
   { C(cookie_key_lifetime),  &type_integer,      validate_positive },
   { C(dbversion),        &type_integer,          validate_positive },
+  { C(default_rights),   &type_rights,           validate_any },
   { C(device),           &type_string,           validate_any },
   { C(gap),              &type_integer,          validate_non_negative },
   { C(history),          &type_integer,          validate_positive },
   { C(device),           &type_string,           validate_any },
   { C(gap),              &type_integer,          validate_non_negative },
   { C(history),          &type_integer,          validate_positive },
@@ -1167,7 +1189,26 @@ static void config_postdefaults(struct config *c,
     c->sample_format.bits = 16;
     c->sample_format.endian = ENDIAN_NATIVE;
     break; 
     c->sample_format.bits = 16;
     c->sample_format.endian = ENDIAN_NATIVE;
     break; 
- }
+  }
+  if(!c->default_rights) {
+    rights_type r = RIGHTS__MASK & ~(RIGHT_ADMIN|RIGHT_REGISTER
+                                    |RIGHT_MOVE__MASK
+                                    |RIGHT_SCRATCH__MASK
+                                    |RIGHT_REMOVE__MASK);
+    /* The idea is to approximate the meaning of the old 'restrict' directive
+     * in the default rights if they are not overridden. */
+    if(c->restrictions & RESTRICT_SCRATCH)
+      r |= RIGHT_SCRATCH_MINE|RIGHT_SCRATCH_RANDOM;
+    else
+      r |= RIGHT_SCRATCH_ANY;
+    if(!(c->restrictions & RESTRICT_MOVE))
+      r |= RIGHT_MOVE_ANY;
+    if(c->restrictions & RESTRICT_REMOVE)
+      r |= RIGHT_REMOVE_MINE;
+    else
+      r |= RIGHT_REMOVE_ANY;
+    c->default_rights = r;
+  }
 }
 
 /** @brief (Re-)read the config file
 }
 
 /** @brief (Re-)read the config file
@@ -1210,6 +1251,13 @@ int config_read(int server) {
   config_postdefaults(c, server);
   /* everything is good so we shall use the new config */
   config_free(config);
   config_postdefaults(c, server);
   /* everything is good so we shall use the new config */
   config_free(config);
+  /* warn about obsolete directives */
+  if(c->restrictions)
+    error(0, "'restrict' will be removed in a future version");
+  if(c->allow.n)
+    error(0, "'allow' will be removed in a future version");
+  if(c->trust.n)
+    error(0, "'trust' will be removed in a future version");
   config = c;
   return 0;
 }
   config = c;
   return 0;
 }
index eb028b05105c183694bb2ce0c5895a032111b106..f08b866e26fb46166a03ab374ebc84f7a10646ce 100644 (file)
@@ -25,6 +25,7 @@
 #define CONFIGURATION_H
 
 #include "speaker-protocol.h"
 #define CONFIGURATION_H
 
 #include "speaker-protocol.h"
+#include "rights.h"
 
 struct real_pcre;
 
 
 struct real_pcre;
 
@@ -251,6 +252,9 @@ struct config {
 
   /** @brief Signing key lifetime in seconds */
   long cookie_key_lifetime;
 
   /** @brief Signing key lifetime in seconds */
   long cookie_key_lifetime;
+
+  /** @brief Default rights for a new user */
+  rights_type default_rights;
   
   /* derived values: */
   int nparts;                          /* number of distinct name parts */
   
   /* derived values: */
   int nparts;                          /* number of distinct name parts */
index 5a9935bac1f102715305e77de4833073f650b633..d03eae10ba9dc3d6b2d838d470cd32b98c47edba 100644 (file)
@@ -75,28 +75,6 @@ char *rights_string(rights_type r) {
   return d->vec;
 }
 
   return d->vec;
 }
 
-/** @brief Compute default rights for a new user
- * @return Default rights value
- */
-rights_type default_rights(void) {
-  /* TODO get rights from config */
-  rights_type r = RIGHTS__MASK & ~(RIGHT_ADMIN|RIGHT_REGISTER
-                                   |RIGHT_MOVE__MASK
-                                   |RIGHT_SCRATCH__MASK
-                                   |RIGHT_REMOVE__MASK);
-  if(config->restrictions & RESTRICT_SCRATCH)
-    r |= RIGHT_SCRATCH_MINE|RIGHT_SCRATCH_RANDOM;
-  else
-    r |= RIGHT_SCRATCH_ANY;
-  if(!(config->restrictions & RESTRICT_MOVE))
-    r |= RIGHT_MOVE_ANY;
-  if(config->restrictions & RESTRICT_REMOVE)
-    r |= RIGHT_REMOVE_MINE;
-  else
-    r |= RIGHT_REMOVE_ANY;
-  return r;
-}
-
 /** @brief Parse a rights list
  * @param s Rights list in string form
  * @param rp Where to store rights, or NULL to just validate
 /** @brief Parse a rights list
  * @param s Rights list in string form
  * @param rp Where to store rights, or NULL to just validate
index 61927722fb502e4ba28e6d5d516d5fc523cb57ed..fb2d6254f4add7f3f8a6d200d1a45541e33b7c0e 100644 (file)
 /** @brief Unsigned type big enough for rights */
 typedef uint32_t rights_type;
 
 /** @brief Unsigned type big enough for rights */
 typedef uint32_t rights_type;
 
-rights_type default_rights(void);
 char *rights_string(rights_type r);
 int parse_rights(const char *s, rights_type *rp);
 
 char *rights_string(rights_type r);
 int parse_rights(const char *s, rights_type *rp);
 
index 2aed9a46c5ee8dd352f3a159146401a2f2588515..d4e7f3052ba82739a799fb399c40276176bf25a9 100644 (file)
@@ -2455,9 +2455,9 @@ static int one_old_user(const char *user, const char *password,
   if(!strcmp(user, "root"))
     rights = "all";
   else if(trusted(user))
   if(!strcmp(user, "root"))
     rights = "all";
   else if(trusted(user))
-    rights = rights_string(default_rights()|RIGHT_ADMIN);
+    rights = rights_string(config->default_rights|RIGHT_ADMIN|RIGHT_RESCAN);
   else
   else
-    rights = rights_string(default_rights());
+    rights = rights_string(config->default_rights);
   return create_user(user, password, rights, 0/*email*/, tid, DB_NOOVERWRITE);
 }
 
   return create_user(user, password, rights, 0/*email*/, tid, DB_NOOVERWRITE);
 }
 
index 7c0d3b39cd6908f9e7320200ef363d2e080dc135..807a2766cd882f57d2efff6e0f96f1e5a6a65ded 100644 (file)
@@ -1077,7 +1077,7 @@ static int c_revoke(struct conn *c,
 static int c_adduser(struct conn *c,
                     char **vec,
                     int attribute((unused)) nvec) {
 static int c_adduser(struct conn *c,
                     char **vec,
                     int attribute((unused)) nvec) {
-  if(trackdb_adduser(vec[0], vec[1], default_rights(), 0))
+  if(trackdb_adduser(vec[0], vec[1], config->default_rights, 0))
     sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n");
   else
     sink_writes(ev_writer_sink(c->w), "250 User created\n");
     sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n");
   else
     sink_writes(ev_writer_sink(c->w), "250 User created\n");
index d4e3472b54693613cfa505e13efb1286591c100f..8262a036f685be1ab483b01c1005290707192711 100644 (file)
@@ -180,7 +180,6 @@ stopword 21 22 23 24 25 26 27 28 29 30
 stopword the a an and to too in on of we i am as im for is
 username fred
 password fredpass
 stopword the a an and to too in on of we i am as im for is
 username fred
 password fredpass
-trust fred root
 plugins
 plugins %s/plugins
 plugins %s/plugins/.libs
 plugins
 plugins %s/plugins
 plugins %s/plugins/.libs
index 84018404802b493a6a672ad3aab40d13125c08d4..507199a10e33c4287807b91b4a7f08dc66ea8dda 100755 (executable)
@@ -55,7 +55,6 @@ def test():
                          "--dump", dump])
     print " changing track pref"
     c.set(track, "foo", "after dump");
                          "--dump", dump])
     print " changing track pref"
     c.set(track, "foo", "after dump");
-    print c.get(track, "foo")
     assert c.get(track, "foo") == "after dump", "checking track foo=after dump"
     print " changing global pref"
     c.setglobal("foo", "after dump");
     assert c.get(track, "foo") == "after dump", "checking track foo=after dump"
     print " changing global pref"
     c.setglobal("foo", "after dump");
index 61417148a345e36067d6684c215b53edfeb4979f..3bab5816aab1dd79c70a76e2788110819157c54c 100755 (executable)
@@ -25,6 +25,7 @@ def test():
     print " testing upgrade from old versions"
     open("%s/config" % dtest.testroot, "a").write(
       """allow fred fredpass
     print " testing upgrade from old versions"
     open("%s/config" % dtest.testroot, "a").write(
       """allow fred fredpass
+trust fred
 """)
     dtest.start_daemon()
     print " checking can log in after upgrade"
 """)
     dtest.start_daemon()
     print " checking can log in after upgrade"