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
\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.
#include <pcre.h>
#include <signal.h>
+#include "rights.h"
#include "configuration.h"
#include "mem.h"
#include "log.h"
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,
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 */
{ 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->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
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;
}
#define CONFIGURATION_H
#include "speaker-protocol.h"
+#include "rights.h"
struct real_pcre;
/** @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 */
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 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);
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
- rights = rights_string(default_rights());
+ rights = rights_string(config->default_rights);
return create_user(user, password, rights, 0/*email*/, tid, DB_NOOVERWRITE);
}
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");
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
"--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");
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"