X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~mdw/git/disorder/blobdiff_plain/eb5dc014179415a0e5476e986519ac96c36221f9..fce810c27ad09dd73706100435a6e65af0a67604:/server/server.c diff --git a/server/server.c b/server/server.c index ef32151..54dfe55 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 @@ -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; @@ -607,7 +608,7 @@ static int c_get(struct conn *c, const char *v; if(vec[1][0] != '_' && (v = trackdb_get(vec[0], vec[1]))) - sink_printf(ev_writer_sink(c->w), "252 %s\n", v); + sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(v)); else sink_writes(ev_writer_sink(c->w), "555 not found\n"); return 1; @@ -623,7 +624,7 @@ static int c_length(struct conn *c, return 1; } if((v = trackdb_get(track, "_length"))) - sink_printf(ev_writer_sink(c->w), "252 %s\n", v); + sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(v)); else sink_writes(ev_writer_sink(c->w), "550 not found\n"); return 1; @@ -925,7 +926,7 @@ static int c_part(struct conn *c, char **vec, int attribute((unused)) nvec) { sink_printf(ev_writer_sink(c->w), "252 %s\n", - trackdb_getpart(vec[0], vec[1], vec[2])); + quoteutf8(trackdb_getpart(vec[0], vec[1], vec[2]))); return 1; } @@ -938,7 +939,7 @@ static int c_resolve(struct conn *c, sink_writes(ev_writer_sink(c->w), "550 cannot resolve track\n"); return 1; } - sink_printf(ev_writer_sink(c->w), "252 %s\n", track); + sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(track)); return 1; } @@ -975,7 +976,7 @@ static int c_get_global(struct conn *c, const char *s = trackdb_get_global(vec[0]); if(s) - sink_printf(ev_writer_sink(c->w), "252 %s\n", s); + sink_printf(ev_writer_sink(c->w), "252 %s\n", quoteutf8(s)); else sink_writes(ev_writer_sink(c->w), "555 not found\n"); return 1; @@ -1076,8 +1077,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], 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 +1100,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; @@ -1152,6 +1164,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 +1223,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 +1255,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 }, @@ -1352,15 +1405,10 @@ static int listen_callback(ev_source *ev, c->l = l; c->rights = 0; gcry_randomize(c->nonce, sizeof c->nonce, GCRY_STRONG_RANDOM); - if(!strcmp(config->authorization_algorithm, "sha1") - || !strcmp(config->authorization_algorithm, "SHA1")) { - sink_printf(ev_writer_sink(c->w), "231 %s\n", - hex(c->nonce, sizeof c->nonce)); - } else { - sink_printf(ev_writer_sink(c->w), "231 %s %s\n", - config->authorization_algorithm, - hex(c->nonce, sizeof c->nonce)); - } + sink_printf(ev_writer_sink(c->w), "231 %d %s %s\n", + 2, + config->authorization_algorithm, + hex(c->nonce, sizeof c->nonce)); return 0; }