X-Git-Url: https://git.distorted.org.uk/~mdw/disorder/blobdiff_plain/04e1fa7cf5163aa784baaf3292ccb3b49e296410..158d096132f284c409fe1954457c67d77caf796c:/server/server.c diff --git a/server/server.c b/server/server.c index 807a276..8d49193 100644 --- a/server/server.c +++ b/server/server.c @@ -66,6 +66,7 @@ #include "cache.h" #include "unicode.h" #include "cookies.h" +#include "base64.h" #ifndef NONCE_SIZE # define NONCE_SIZE 16 @@ -247,7 +248,7 @@ static int c_remove(struct conn *c, char **vec, r = RIGHT_REMOVE_RANDOM; if(!(c->rights & r)) { sink_writes(ev_writer_sink(c->w), - "550 Not authorized to remove that track\n"); + "510 Not authorized to remove that track\n"); return 1; } queue_remove(q, c->who); @@ -285,7 +286,7 @@ static int c_scratch(struct conn *c, r = RIGHT_SCRATCH_RANDOM; if(!(c->rights & r)) { sink_writes(ev_writer_sink(c->w), - "550 Not authorized to scratch that track\n"); + "510 Not authorized to scratch that track\n"); return 1; } scratch(c->who, nvec == 1 ? vec[0] : 0); @@ -433,7 +434,7 @@ static int c_user(struct conn *c, } password = kvp_get(k, "password"); if(!password) password = ""; - if(parse_rights(kvp_get(k, "rights"), &rights)) { + if(parse_rights(kvp_get(k, "rights"), &rights, 1)) { error(0, "error parsing rights for %s", vec[0]); sink_writes(ev_writer_sink(c->w), "530 authentication failed\n"); return 1; @@ -753,7 +754,7 @@ static int c_volume(struct conn *c, } rights = set ? RIGHT_VOLUME : RIGHT_READ; if(!(c->rights & rights)) { - sink_writes(ev_writer_sink(c->w), "530 Prohibited\n"); + sink_writes(ev_writer_sink(c->w), "510 Prohibited\n"); return 1; } if(mixer_control(&l, &r, set)) @@ -876,7 +877,7 @@ static int c_move(struct conn *c, } if(!has_move_rights(c, &q, 1)) { sink_writes(ev_writer_sink(c->w), - "550 Not authorized to move that track\n"); + "510 Not authorized to move that track\n"); return 1; } n = queue_move(q, atoi(vec[1]), c->who); @@ -910,7 +911,7 @@ static int c_moveafter(struct conn *c, } if(!has_move_rights(c, qs, nvec)) { sink_writes(ev_writer_sink(c->w), - "550 Not authorized to move those tracks\n"); + "510 Not authorized to move those tracks\n"); return 1; } queue_moveafter(q, nvec, qs, c->who); @@ -1040,14 +1041,15 @@ static int c_cookie(struct conn *c, return 1; } /* Log in */ - c->who = vec[0]; + c->who = user; c->cookie = vec[0]; c->rights = rights; if(strcmp(host, "local")) { info("S%x %s connected with cookie from %s", c->tag, user, host); c->rights |= RIGHT__LOCAL; } - sink_writes(ev_writer_sink(c->w), "230 OK\n"); + /* Response contains username so client knows who they are acting as */ + sink_printf(ev_writer_sink(c->w), "232 %s\n", quoteutf8(user)); return 1; } @@ -1076,8 +1078,19 @@ static int c_revoke(struct conn *c, static int c_adduser(struct conn *c, char **vec, - int attribute((unused)) nvec) { - if(trackdb_adduser(vec[0], vec[1], config->default_rights, 0)) + int nvec) { + const char *rights; + + if(nvec > 2) { + rights = vec[2]; + if(parse_rights(vec[2], 0, 1)) { + sink_writes(ev_writer_sink(c->w), "550 Invalid rights list\n"); + return -1; + } + } else + rights = config->default_rights; + if(trackdb_adduser(vec[0], vec[1], rights, + 0/*email*/, 0/*confirmation*/)) sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n"); else sink_writes(ev_writer_sink(c->w), "250 User created\n"); @@ -1088,7 +1101,7 @@ static int c_deluser(struct conn *c, char **vec, int attribute((unused)) nvec) { if(trackdb_deluser(vec[0])) - sink_writes(ev_writer_sink(c->w), "550 Cannot deleted user\n"); + sink_writes(ev_writer_sink(c->w), "550 Cannot delete user\n"); else sink_writes(ev_writer_sink(c->w), "250 User deleted\n"); return 1; @@ -1108,7 +1121,7 @@ static int c_edituser(struct conn *c, else sink_writes(ev_writer_sink(c->w), "250 OK\n"); } else - sink_writes(ev_writer_sink(c->w), "550 Restricted to administrators\n"); + sink_writes(ev_writer_sink(c->w), "510 Restricted to administrators\n"); return 1; } @@ -1132,7 +1145,7 @@ static int c_userinfo(struct conn *c, else sink_writes(ev_writer_sink(c->w), "550 No such user\n"); } else - sink_writes(ev_writer_sink(c->w), "550 Restricted to administrators\n"); + sink_writes(ev_writer_sink(c->w), "510 Restricted to administrators\n"); return 1; } @@ -1152,6 +1165,45 @@ static int c_users(struct conn *c, return 1; /* completed */ } +static int c_register(struct conn *c, + char **vec, + int attribute((unused)) nvec) { + char *buf, *cs; + size_t bufsize; + int offset; + + /* The confirmation string is base64(username;nonce) */ + bufsize = strlen(vec[0]) + NONCE_SIZE + 2; + buf = xmalloc_noptr(bufsize); + offset = byte_snprintf(buf, bufsize, "%s;", vec[0]); + gcry_randomize(buf + offset, NONCE_SIZE, GCRY_STRONG_RANDOM); + cs = mime_to_base64((uint8_t *)buf, offset + NONCE_SIZE); + if(trackdb_adduser(vec[0], vec[1], config->default_rights, vec[2], cs)) + sink_writes(ev_writer_sink(c->w), "550 Cannot create user\n"); + else + sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(cs)); + return 1; +} + +static int c_confirm(struct conn *c, + char **vec, + int attribute((unused)) nvec) { + size_t nuser; + char *user, *sep; + + if(!(user = mime_base64(vec[0], &nuser)) + || !(sep = memchr(user, ';', nuser))) { + sink_writes(ev_writer_sink(c->w), "550 Malformed confirmation string\n"); + return 1; + } + *sep = 0; + if(trackdb_confirm(user, vec[0])) + sink_writes(ev_writer_sink(c->w), "550 Incorrect confirmation string\n"); + else + sink_writes(ev_writer_sink(c->w), "250 OK\n"); + return 1; +} + static const struct command { /** @brief Command name */ const char *name; @@ -1172,8 +1224,9 @@ static const struct command { */ rights_type rights; } commands[] = { - { "adduser", 2, 2, c_adduser, RIGHT_ADMIN|RIGHT__LOCAL }, + { "adduser", 2, 3, c_adduser, RIGHT_ADMIN|RIGHT__LOCAL }, { "allfiles", 0, 2, c_allfiles, RIGHT_READ }, + { "confirm", 1, 1, c_confirm, 0 }, { "cookie", 1, 1, c_cookie, 0 }, { "deluser", 1, 1, c_deluser, RIGHT_ADMIN|RIGHT__LOCAL }, { "dirs", 0, 2, c_dirs, RIGHT_READ }, @@ -1203,6 +1256,7 @@ static const struct command { { "random-enabled", 0, 0, c_random_enabled, RIGHT_READ }, { "recent", 0, 0, c_recent, RIGHT_READ }, { "reconfigure", 0, 0, c_reconfigure, RIGHT_ADMIN }, + { "register", 3, 3, c_register, RIGHT_REGISTER|RIGHT__LOCAL }, { "remove", 1, 1, c_remove, RIGHT_REMOVE__MASK }, { "rescan", 0, 0, c_rescan, RIGHT_RESCAN }, { "resolve", 1, 1, c_resolve, RIGHT_READ }, @@ -1255,7 +1309,7 @@ static int command(struct conn *c, char *line) { else { if(commands[n].rights && !(c->rights & commands[n].rights)) { - sink_writes(ev_writer_sink(c->w), "530 Prohibited\n"); + sink_writes(ev_writer_sink(c->w), "510 Prohibited\n"); return 1; } ++vec;