]> mj.ucw.cz Git - subauth.git/blobdiff - server/cmd.c
Server: create_token returns the ident of the new token
[subauth.git] / server / cmd.c
index 4b10368cc8efad80649e27ffbfa32f19a7d6a280..8959d078c8d94e52871e5b28c646be9bfbc0d43f 100644 (file)
@@ -236,6 +236,20 @@ static void cmd_set_passwd(struct client *c)
   cmd_ok(c);
 }
 
+static void cmd_delete_passwd(struct client *c)
+{
+  struct auth_acct *aa = cmd_need_target_acct(c);
+  struct auth_token *at = auth_find_token_passwd(aa);
+  if (!at)
+    cmd_error(c, "No password set");
+
+  msg(L_INFO, "Deleted password: login=<%s> zone=<%s>", aa->user->login, aa->zone->name);
+  auth_delete_token(at);
+
+  db_write();
+  cmd_ok(c);
+}
+
 static void cmd_create_token(struct client *c)
 {
   struct auth_acct *aa = cmd_need_target_acct(c);
@@ -246,10 +260,14 @@ static void cmd_create_token(struct client *c)
   if (clist_size(&aa->tokens) >= aa->zone->allow_tokens)
     cmd_error(c, "Maximum number of tokens was reached");
 
+  const char *comment = get_string(c->request, "comment");
+  if (comment && strlen(comment) > max_comment_size)
+    cmd_error(c, "Comment too long");
+
   struct auth_token *at = auth_create_token(aa);
-  char *tok = auth_set_token_generated(at, get_string(c->request, "comment"));
+  char *tok = auth_set_token_generated(at, comment, c->pool);
   set_string(c, c->reply, "token", tok);
-  xfree(tok);
+  set_string(c, c->reply, "ident", at->ident);
 
   msg(L_INFO, "Created token: login=<%s> zone=<%s> id=<%s>", aa->user->login, aa->zone->name, at->ident);
 
@@ -257,12 +275,123 @@ static void cmd_create_token(struct client *c)
   cmd_ok(c);
 }
 
+static void cmd_delete_token(struct client *c)
+{
+  struct auth_acct *aa = cmd_need_target_acct(c);
+  const char *ident = cmd_need_string(c, "ident");
+  bool all = !strcmp(ident, "*");
+  bool matched = 0;
+
+  struct auth_token *tmp;
+  CLIST_FOR_EACH_DELSAFE(struct auth_token *, at, aa->tokens, tmp)
+    if (at->type == TOKEN_GENERATED && (all || !strcmp(at->ident, ident)))
+      {
+       matched = 1;
+       msg(L_INFO, "Deleted token: login=<%s> zone=<%s> id=<%s>", aa->user->login, aa->zone->name, at->ident);
+       auth_delete_token(at);
+      }
+
+  if (!all && !matched)
+    cmd_error(c, "No such token");
+
+  db_write();
+  cmd_ok(c);
+}
+
+static void cmd_change_token(struct client *c)
+{
+  struct auth_acct *aa = cmd_need_target_acct(c);
+  const char *ident = cmd_need_string(c, "ident");
+  struct auth_token *at = auth_find_token_generated(aa, ident);
+  if (!at)
+    cmd_error(c, "No such token");
+
+  const char *comment = get_string(c->request, "comment");
+  if (comment && !strcmp(comment, ""))
+    comment = NULL;
+  auth_change_token_comment(at, comment);
+
+  msg(L_INFO, "Changed token: login=<%s> zone=<%s> id=<%s>", aa->user->login, aa->zone->name, at->ident);
+
+  db_write();
+  cmd_ok(c);
+}
+
+static void cmd_create_temp(struct client *c)
+{
+  struct auth_acct *aa = cmd_need_target_acct(c);
+
+  uint validity;
+  if (!get_uint(c->request, "validity", &validity))
+    cmd_error(c, "Validity must be given");
+
+  if (!aa->zone->max_temp_validity)
+    cmd_error(c, "This zone does not allow temporary tokens");
+
+  if (validity > aa->zone->max_temp_validity)
+    cmd_error(c, "This zone limits temporary token validity to %d seconds", aa->zone->max_temp_validity);
+
+  char *tok = temp_generate(aa->zone->name, aa->user->login, validity, c->pool);
+  set_string(c, c->reply, "token", tok);
+
+  const char *shortened = temp_shorten(tok, c->pool);
+
+  msg(L_INFO, "Created temp token: login=<%s> zone=<%s> temp=<%s> validity=%u", aa->user->login, aa->zone->name, shortened, validity);
+
+  cmd_ok(c);
+}
+
 static void cmd_login_fake(struct client *c, const char *passwd)
 {
   auth_check_token(auth_fake_token, passwd);
   cmd_error(c, "Invalid password");
 }
 
+static void cmd_login_by_temp(struct client *c, struct auth_zone *az, const char *given_passwd)
+{
+  const char *login = cmd_need_string(c, "login");
+  const char *shortened = temp_shorten(given_passwd, c->pool);
+
+  const char *reason = temp_check(az->name, login, given_passwd, c->pool);
+  if (reason)
+    {
+      msg(L_INFO, "Login failed: %s user=<%s> zone=<%s> temp=<%s>", reason, login, az->name, shortened);
+      goto reject;
+    }
+
+  /*
+   * The following checks test for improbable things like user
+   * disappearing since the token has been issued.
+   */
+
+  if (!az->max_temp_validity)
+    {
+      msg(L_INFO, "Login failed: Temporary tokens no longer accepted for zone=<%s>", az->name);
+      goto reject;
+    }
+
+  struct auth_user *au = auth_find_user(login, 0);
+  if (!au)
+    {
+      msg(L_INFO, "Login failed: No user=<%s> temp=<%s>", login, shortened);
+      goto reject;
+    }
+
+  struct auth_acct *aa = auth_find_acct(au, az, 0);
+  if (!aa)
+    {
+      msg(L_INFO, "Login failed: No account user=<%s> zone=<%s> temp=<%s>", login, az->name, shortened);
+      goto reject;
+    }
+
+  msg(L_INFO, "Login successful: user=<%s> zone=<%s> temp=<%s>", login, az->name, shortened);
+  cmd_ok(c);
+  return;
+
+reject:
+  cmd_error(c, "Temporary token refused");
+}
+
 static void cmd_login(struct client *c)
 {
   struct auth_zone *az = cmd_need_zone(c);
@@ -285,6 +414,9 @@ static void cmd_login(struct client *c)
       passwd = passbuf;
     }
 
+  if (ident && !strcmp(ident, "t"))
+    return cmd_login_by_temp(c, az, given_passwd);
+
   const char *login = cmd_need_string(c, "login");
   struct auth_user *au = auth_find_user(login, 0);
   if (!au)
@@ -325,15 +457,18 @@ static void cmd_list_accts(struct client *c)
 {
   const char *login = cmd_need_target_login(c);
 
-  struct auth_user *au = auth_find_user(login, 0);
-  if (!au)
-    cmd_error(c, "No such user");
-
   struct json_context *js = c->json;
-  set_string(c, c->reply, "login", au->login);
+  set_string(c, c->reply, "login", login);
   struct json_node *jas = json_new_array(js);
   json_object_set(c->reply, "accounts", jas);
 
+  struct auth_user *au = auth_find_user(login, 0);
+  if (!au)
+    {
+      cmd_ok(c);
+      return;
+    }
+
   CLIST_FOR_EACH(struct auth_acct *, aa, au->accounts)
     {
       struct json_node *ja = json_new_object(js);
@@ -381,6 +516,7 @@ static void cmd_list_zones(struct client *c)
       set_string(c, jz, "desc", az->desc);
       set_uint(c, jz, "allow-passwd", az->allow_passwd);
       set_uint(c, jz, "allow-tokens", az->allow_tokens);
+      set_uint(c, jz, "max-temp-validity", az->max_temp_validity);
     }
 
   cmd_ok(c);
@@ -396,7 +532,11 @@ static const struct command command_table[] = {
   { "create-acct",     cmd_create_acct },
   { "delete-acct",     cmd_delete_acct },
   { "create-token",    cmd_create_token },
+  { "delete-token",    cmd_delete_token },
+  { "change-token",    cmd_change_token },
   { "set-passwd",      cmd_set_passwd },
+  { "delete-passwd",   cmd_delete_passwd },
+  { "create-temp",     cmd_create_temp },
   { "login",           cmd_login },
   { "list-accts",      cmd_list_accts },
   { "list-zones",      cmd_list_zones },