+
+static int c_cookie(struct conn *c,
+ char **vec,
+ int attribute((unused)) nvec) {
+ const char *host;
+ char *user;
+
+ /* Can't log in twice on the same connection */
+ if(c->who) {
+ sink_writes(ev_writer_sink(c->w), "530 already authenticated\n");
+ return 1;
+ }
+ /* Get some kind of peer identifcation */
+ if(!(host = connection_host(c))) {
+ sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
+ return 1;
+ }
+ /* Check the cookie */
+ user = verify_cookie(vec[0]);
+ if(!user) {
+ sink_writes(ev_writer_sink(c->w), "530 authentication failure\n");
+ return 1;
+ }
+ /* Log in */
+ c->who = user;
+ c->cookie = vec[0];
+ if(strcmp(host, "local"))
+ info("S%x %s connected with cookie from %s", c->tag, user, host);
+ sink_writes(ev_writer_sink(c->w), "230 OK\n");
+ return 1;
+}
+
+static int c_make_cookie(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ const char *cookie = make_cookie(c->who);
+
+ if(cookie)
+ sink_printf(ev_writer_sink(c->w), "252 %s\n", cookie);
+ else
+ sink_writes(ev_writer_sink(c->w), "550 Cannot create cookie\n");
+ return 1;
+}
+
+static int c_revoke(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ if(c->cookie) {
+ revoke_cookie(c->cookie);
+ sink_writes(ev_writer_sink(c->w), "250 OK\n");
+ } else
+ sink_writes(ev_writer_sink(c->w), "550 Did not log in with cookie\n");
+ return 1;
+}
+
+static int c_adduser(struct conn *c,
+ char **vec,
+ int attribute((unused)) nvec) {
+ /* TODO local only */
+ if(trackdb_adduser(vec[0], vec[1], 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");
+ return 1;
+}
+
+static int c_deluser(struct conn *c,
+ char **vec,
+ int attribute((unused)) nvec) {
+ /* TODO local only */
+ if(trackdb_deluser(vec[0]))
+ sink_writes(ev_writer_sink(c->w), "550 Cannot deleted user\n");
+ else
+ sink_writes(ev_writer_sink(c->w), "250 User deleted\n");
+ return 1;
+}
+
+static int c_edituser(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ sink_writes(ev_writer_sink(c->w), "550 Not implemented\n"); /* TODO */
+ return 1;
+}
+
+static int c_userinfo(struct conn *c,
+ char attribute((unused)) **vec,
+ int attribute((unused)) nvec) {
+ sink_writes(ev_writer_sink(c->w), "550 Not implemented\n"); /* TODO */
+ return 1;
+}
+