]> mj.ucw.cz Git - subauth.git/commitdiff
Account management using password authentication
authorJan Hadrava <had@kam.mff.cuni.cz>
Fri, 6 Sep 2019 21:26:24 +0000 (23:26 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 10 Sep 2019 08:29:28 +0000 (10:29 +0200)
PROTOCOL
client/subauth.1.txt
client/subauth.c
etc/subauthd
server/auth.c
server/cmd.c
server/subauthd.c
server/subauthd.h

index 9b910c4524e1628ec33ae842ef4f1b0f47bf803a..edf13691f2dfe41891487596a23c57ed0eef72dc 100644 (file)
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -12,8 +12,10 @@ Replies always have the "error" attribute set; it contains an error
 message or an empty string to indicate success.
 
 Some operations require root privileges. Other operations are
 message or an empty string to indicate success.
 
 Some operations require root privileges. Other operations are
-unprivileged if no login name present, or if it matches the UID
-of the requesting user.
+unprivileged if no login name present, or if the correct "auth-passwd"
+is provided and target user has allowed administration of their
+account using a password authentication. Only regular password can be
+used for such authentication, tokens are not accepted.
 
 # No operation (unprivileged)
 {
 
 # No operation (unprivileged)
 {
@@ -38,6 +40,7 @@ of the requesting user.
 {
        "cmd": "create-token",
        "login": "login name",
 {
        "cmd": "create-token",
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone",
        "comment": "optional comment"
 }
        "zone": "auth zone",
        "comment": "optional comment"
 }
@@ -51,6 +54,7 @@ of the requesting user.
 {
        "cmd": "delete-token",
        "login": "login name",
 {
        "cmd": "delete-token",
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone",
        "ident": "token id"                     # "*" for all tokens for the login+zone
 }
        "zone": "auth zone",
        "ident": "token id"                     # "*" for all tokens for the login+zone
 }
@@ -59,6 +63,7 @@ of the requesting user.
 {
        "cmd": "change-token"
        "login": "login name",
 {
        "cmd": "change-token"
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone",
        "ident": "token id",
        "comment": "new comment"                # optional
        "zone": "auth zone",
        "ident": "token id",
        "comment": "new comment"                # optional
@@ -68,6 +73,7 @@ of the requesting user.
 {
        "cmd": "set-passwd",
        "login": "login name",
 {
        "cmd": "set-passwd",
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone",
        "passwd": "new password"
 }
        "zone": "auth zone",
        "passwd": "new password"
 }
@@ -76,6 +82,7 @@ of the requesting user.
 {
        "cmd": "delete-passwd",
        "login": "login name",
 {
        "cmd": "delete-passwd",
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone"
 }
 
        "zone": "auth zone"
 }
 
@@ -83,6 +90,7 @@ of the requesting user.
 {
        "cmd": "create-temp",
        "login": "login name",
 {
        "cmd": "create-temp",
        "login": "login name",
+       "auth-passwd": "current password",
        "zone": "auth zone",
        "validity": seconds             # Requested token validity
 }
        "zone": "auth zone",
        "validity": seconds             # Requested token validity
 }
@@ -99,6 +107,15 @@ of the requesting user.
        "passwd": "password or token"
 }
 
        "passwd": "password or token"
 }
 
+# Allow/disallow management of selected account using password
+{
+       "cmd": "allow-passwd-auth",
+       "login": "login name",
+       "auth-passwd": "current password",
+       "zone": "auth zone",
+       "allow": integer
+}
+
 # List user's accounts and tokens
 {
        "cmd": "list-accts",
 # List user's accounts and tokens
 {
        "cmd": "list-accts",
@@ -110,6 +127,7 @@ of the requesting user.
        "accounts": [
                {
                        "zone": "auth zone",
        "accounts": [
                {
                        "zone": "auth zone",
+                       "allow-passwd-auth": integer,           # Can anybody manage this account using its password?
                        "tokens": [
                                {
                                        "type": "token type",   # passwd/token
                        "tokens": [
                                {
                                        "type": "token type",   # passwd/token
@@ -135,6 +153,7 @@ of the requesting user.
                        "desc": "human-readable description",
                        "allow-passwd": integer,                # Does the zone support passwords?
                        "allow-tokens": integer,                # Does the zone support auth tokens?
                        "desc": "human-readable description",
                        "allow-passwd": integer,                # Does the zone support passwords?
                        "allow-tokens": integer,                # Does the zone support auth tokens?
+                       "allow-passwd-auth": integer,           # Does the zone support password authentication for account management?
                        "max-temp-validity": seconds            # Maximum validity of temp tokens
                                                                # (if no temp tokens supported)
                }
                        "max-temp-validity": seconds            # Maximum validity of temp tokens
                                                                # (if no temp tokens supported)
                }
index d047f55b9e7f97f9722ea45bfdcd9579468a38ca..9db0e2d24fa564d0967b93c5a0b551ba629558e2 100644 (file)
@@ -96,6 +96,15 @@ OPERATIONS
        in the given zone. Requires *--zone*. Optionally, you can specify a *--user*
        to test somebody else's credentials.
 
        in the given zone. Requires *--zone*. Optionally, you can specify a *--user*
        to test somebody else's credentials.
 
+*--allow-passwd-auth*::
+       Allow administration of our account in a given zone to anybody, who
+       knows our password. Requires *--zone*. Depending on the local setup,
+       this may for example enable passowrd changes from webmail interface.
+
+*--disallow-passwd-auth*::
+       Prevent other users from administration of our account in a given zone
+       using password authentication. Requires *--zone*.
+
 *Administrator commands*
 
 *--create-acct*::
 *Administrator commands*
 
 *--create-acct*::
@@ -131,6 +140,11 @@ OPTIONS
        which is either "*h*", "*m*", or "*s*". Maximum lifetime can be limited
        by zone configuration.
 
        which is either "*h*", "*m*", or "*s*". Maximum lifetime can be limited
        by zone configuration.
 
+*--auth-passwd*::
+       Ask for target user's account passowrd to authorize the operation.
+       Note that password authentication has to be explicitly enabled on
+       target account. Requires *--zone* and *--user*.
+
 *--socket=*'path'::
        Communicate with the subauth daemon through the given socket instead
        of the default one.
 *--socket=*'path'::
        Communicate with the subauth daemon through the given socket instead
        of the default one.
index 6b73750ee2125c27f4f4b4bd4a8c27a1562eb5c0..160c547e5925176e50694fb3cc70e6d80f7c620d 100644 (file)
@@ -30,6 +30,7 @@ static char *arg_ident;
 static char *arg_comment;
 static int debug;
 static char *arg_expire;
 static char *arg_comment;
 static int debug;
 static char *arg_expire;
+static int arg_auth_passwd;
 
 /*** Communication with the daemon ***/
 
 
 /*** Communication with the daemon ***/
 
@@ -72,6 +73,11 @@ static void op_new(const char *op)
   set_string(rq, "cmd", op);
   if (arg_user)
     set_string(rq, "login", arg_user);
   set_string(rq, "cmd", op);
   if (arg_user)
     set_string(rq, "login", arg_user);
+  if (arg_auth_passwd)
+    {
+      char *auth_passwd = xstrdup(getpass("Current password: "));
+      set_string(rq, "auth-passwd", auth_passwd);
+    }
 }
 
 static void op_debug(const char *msg, struct json_node *n)
 }
 
 static void op_debug(const char *msg, struct json_node *n)
@@ -138,12 +144,12 @@ static void cmd_set_passwd(void)
   if (!arg_zone)
     opt_failure("--zone must be given");
 
   if (!arg_zone)
     opt_failure("--zone must be given");
 
+  op_new("set-passwd");
   char *passwd = xstrdup(getpass("New password: "));
   char *again = xstrdup(getpass("Confirm password: "));
   if (strcmp(passwd, again))
     die("Passwords do not match");
 
   char *passwd = xstrdup(getpass("New password: "));
   char *again = xstrdup(getpass("Confirm password: "));
   if (strcmp(passwd, again))
     die("Passwords do not match");
 
-  op_new("set-passwd");
   set_string(rq, "zone", arg_zone);
   set_string(rq, "passwd", passwd);
 
   set_string(rq, "zone", arg_zone);
   set_string(rq, "passwd", passwd);
 
@@ -248,17 +254,20 @@ static void cmd_list(void)
       return;
     }
 
       return;
     }
 
-  printf("%-16s %-6s %-5s %-19s  %s\n",
-    "Zone", "Type", "Ident", "Last modified", "Comment");
+  printf("%-16s %-6s %-5s %-19s %-8s  %s\n",
+    "Zone", "Type", "Ident", "Last modified", "PassAuth", "Comment");
   for (uint i=0; i < GARY_SIZE(jas); i++)
     {
       struct json_node *ja = jas[i];
       struct json_node *jz = need_child(ja, "zone", JSON_STRING);
       struct json_node **jts = need_child(ja, "tokens", JSON_ARRAY)->elements;
   for (uint i=0; i < GARY_SIZE(jas); i++)
     {
       struct json_node *ja = jas[i];
       struct json_node *jz = need_child(ja, "zone", JSON_STRING);
       struct json_node **jts = need_child(ja, "tokens", JSON_ARRAY)->elements;
+      struct json_node *jpassauth = get_child(ja, "allow-passwd-auth", JSON_NUMBER);
 
       if (!GARY_SIZE(jts))
        {
 
       if (!GARY_SIZE(jts))
        {
-         printf("%-16s (no tokens defined)\n", jz->string);
+         printf("%-16s (no tokens defined%s)\n",
+           jz->string,
+           jpassauth ? (jpassauth->number ? ", password auth allowed" : ", password auth disabled") : "");
          continue;
        }
 
          continue;
        }
 
@@ -271,12 +280,13 @@ static void cmd_list(void)
          struct json_node *jlastmod = need_child(lt, "lastmod", JSON_NUMBER);
          time_t lm = jlastmod->number;
          struct tm *tm = localtime(&lm);
          struct json_node *jlastmod = need_child(lt, "lastmod", JSON_NUMBER);
          time_t lm = jlastmod->number;
          struct tm *tm = localtime(&lm);
-         printf("%-16s %-6s %-5s %04d-%02d-%02d %02d:%02d:%02d  %s\n",
+         printf("%-16s %-6s %-5s %04d-%02d-%02d %02d:%02d:%02d %8s  %s\n",
            jz->string,
            jtype->string,
            (jident ? jident->string : "-"),
            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec,
            jz->string,
            jtype->string,
            (jident ? jident->string : "-"),
            tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday,
            tm->tm_hour, tm->tm_min, tm->tm_sec,
+           (jpassauth && jpassauth->number ? "yes" : "-"),
            (jcomment ? jcomment->string : ""));
        }
     }
            (jcomment ? jcomment->string : ""));
        }
     }
@@ -288,7 +298,7 @@ static void cmd_zones(void)
   op_run();
 
   struct json_node **jzs = need_child(rp, "zones", JSON_ARRAY)->elements;
   op_run();
 
   struct json_node **jzs = need_child(rp, "zones", JSON_ARRAY)->elements;
-  printf("%-16s %6s %6s %6s  %s\n", "Zone", "Passwd", "Tokens", "MaxTmp", "Description");
+  printf("%-16s %6s %6s %6s %8s  %s\n", "Zone", "Passwd", "Tokens", "MaxTmp", "PassAuth", "Description");
   for (uint i=0; i < GARY_SIZE(jzs); i++)
     {
       struct json_node *jz = jzs[i];
   for (uint i=0; i < GARY_SIZE(jzs); i++)
     {
       struct json_node *jz = jzs[i];
@@ -296,12 +306,14 @@ static void cmd_zones(void)
       struct json_node *jdesc = get_child(jz, "desc", JSON_STRING);
       struct json_node *jpass = get_child(jz, "allow-passwd", JSON_NUMBER);
       struct json_node *jtokens = get_child(jz, "allow-tokens", JSON_NUMBER);
       struct json_node *jdesc = get_child(jz, "desc", JSON_STRING);
       struct json_node *jpass = get_child(jz, "allow-passwd", JSON_NUMBER);
       struct json_node *jtokens = get_child(jz, "allow-tokens", JSON_NUMBER);
+      struct json_node *jpassauth = get_child(jz, "allow-passwd-auth", JSON_NUMBER);
       struct json_node *jtemp = get_child(jz, "max-temp-validity", JSON_NUMBER);
       struct json_node *jtemp = get_child(jz, "max-temp-validity", JSON_NUMBER);
-      printf("%-16s %6s %6d %6d  %s\n",
+      printf("%-16s %6s %6d %6d %8s  %s\n",
        jname->string,
        (jpass && jpass->number ? "yes" : "-"),
        (jtokens ? (uint) jtokens->number : 0),
        (jtemp ? (uint) jtemp->number : 0),
        jname->string,
        (jpass && jpass->number ? "yes" : "-"),
        (jtokens ? (uint) jtokens->number : 0),
        (jtemp ? (uint) jtemp->number : 0),
+       (jpassauth && jpassauth->number ? "yes" : "-"),
        (jdesc ? jdesc->string : "(no description)"));
     }
 }
        (jdesc ? jdesc->string : "(no description)"));
     }
 }
@@ -368,6 +380,30 @@ static void cmd_temp_token(void)
   printf("%s\n", jt->string);
 }
 
   printf("%s\n", jt->string);
 }
 
+static void cmd_allow_passwd_auth(void)
+{
+  if (!arg_zone)
+    opt_failure("--zone must be given");
+
+  op_new("allow-passwd-auth");
+  set_string(rq, "zone", arg_zone);
+  set_uint(rq, "allow", 1);
+
+  op_run();
+}
+
+static void cmd_disallow_passwd_auth(void)
+{
+  if (!arg_zone)
+    opt_failure("--zone must be given");
+
+  op_new("allow-passwd-auth");
+  set_string(rq, "zone", arg_zone);
+  json_object_set(rq, "allow", json_new_number(js, 0));
+
+  op_run();
+}
+
 static void cmd_raw(void)
 {
   op_new("");
 static void cmd_raw(void)
 {
   op_new("");
@@ -392,6 +428,8 @@ enum command {
   CMD_ZONES,
   CMD_LOGIN,
   CMD_TEMP_TOKEN,
   CMD_ZONES,
   CMD_LOGIN,
   CMD_TEMP_TOKEN,
+  CMD_ALLOW_PASSWD_AUTH,
+  CMD_DISALLOW_PASSWD_AUTH,
   CMD_RAW,
   CMD_MAX
 };
   CMD_RAW,
   CMD_MAX
 };
@@ -409,6 +447,8 @@ void (* const command_handlers[CMD_MAX])(void) = {
   [CMD_ZONES] = cmd_zones,
   [CMD_LOGIN] = cmd_login,
   [CMD_TEMP_TOKEN] = cmd_temp_token,
   [CMD_ZONES] = cmd_zones,
   [CMD_LOGIN] = cmd_login,
   [CMD_TEMP_TOKEN] = cmd_temp_token,
+  [CMD_ALLOW_PASSWD_AUTH] = cmd_allow_passwd_auth,
+  [CMD_DISALLOW_PASSWD_AUTH] = cmd_disallow_passwd_auth,
   [CMD_RAW] = cmd_raw,
 };
 
   [CMD_RAW] = cmd_raw,
 };
 
@@ -427,15 +467,17 @@ static const struct opt_section options = {
     OPT_HELP_OPTION,
     OPT_HELP(""),
     OPT_HELP("User commands:"),
     OPT_HELP_OPTION,
     OPT_HELP(""),
     OPT_HELP("User commands:"),
-    OPT_SWITCH('l', "list",            command, CMD_LIST,              OPT_SINGLE, "\tList tokens for all zones"),
-    OPT_SWITCH(0,   "zones",           command, CMD_ZONES,             OPT_SINGLE, "\tList all known zones"),
-    OPT_SWITCH(0,   "passwd",          command, CMD_SET_PASSWD,        OPT_SINGLE, "\tSet password"),
-    OPT_SWITCH(0,   "delete-passwd",   command, CMD_DELETE_PASSWD,     OPT_SINGLE, "\tRemove password"),
-    OPT_SWITCH(0,   "create-token",    command, CMD_CREATE_TOKEN,      OPT_SINGLE, "\tCreate a new token"),
-    OPT_SWITCH(0,   "delete-token",    command, CMD_DELETE_TOKEN,      OPT_SINGLE, "\tRemove an existing token"),
-    OPT_SWITCH(0,   "change-token",    command, CMD_CHANGE_TOKEN,      OPT_SINGLE, "\tChange the comment of an existing token"),
-    OPT_SWITCH(0,   "login",           command, CMD_LOGIN,             OPT_SINGLE, "\tTry to log in"),
-    OPT_SWITCH(0,   "temp-token",      command, CMD_TEMP_TOKEN,        OPT_SINGLE, "\tCreate a temporary token"),
+    OPT_SWITCH('l', "list",                    command, CMD_LIST,                      OPT_SINGLE, "\tList tokens for all zones"),
+    OPT_SWITCH(0,   "zones",                   command, CMD_ZONES,                     OPT_SINGLE, "\tList all known zones"),
+    OPT_SWITCH(0,   "passwd",                  command, CMD_SET_PASSWD,                OPT_SINGLE, "\tSet password"),
+    OPT_SWITCH(0,   "delete-passwd",           command, CMD_DELETE_PASSWD,             OPT_SINGLE, "\tRemove password"),
+    OPT_SWITCH(0,   "create-token",            command, CMD_CREATE_TOKEN,              OPT_SINGLE, "\tCreate a new token"),
+    OPT_SWITCH(0,   "delete-token",            command, CMD_DELETE_TOKEN,              OPT_SINGLE, "\tRemove an existing token"),
+    OPT_SWITCH(0,   "change-token",            command, CMD_CHANGE_TOKEN,              OPT_SINGLE, "\tChange the comment of an existing token"),
+    OPT_SWITCH(0,   "login",                   command, CMD_LOGIN,                     OPT_SINGLE, "\tTry to log in"),
+    OPT_SWITCH(0,   "temp-token",              command, CMD_TEMP_TOKEN,                OPT_SINGLE, "\tCreate a temporary token"),
+    OPT_SWITCH(0,   "allow-passwd-auth",       command, CMD_ALLOW_PASSWD_AUTH,         OPT_SINGLE, "\tAllow management using password authentication"),
+    OPT_SWITCH(0,   "disallow-passwd-auth",    command, CMD_DISALLOW_PASSWD_AUTH,      OPT_SINGLE, "\tDisallow account management"),
     OPT_HELP(""),
     OPT_HELP("Administrative commands:"),
     OPT_SWITCH(0,   "create-acct",     command, CMD_CREATE_ACCT,       OPT_SINGLE, "\tCreate an account"),
     OPT_HELP(""),
     OPT_HELP("Administrative commands:"),
     OPT_SWITCH(0,   "create-acct",     command, CMD_CREATE_ACCT,       OPT_SINGLE, "\tCreate an account"),
@@ -449,6 +491,7 @@ static const struct opt_section options = {
     OPT_STRING('i', "ident", arg_ident, OPT_REQUIRED_VALUE, "id\tToken ID ('*' for all tokens in zone)"),
     OPT_STRING('c', "comment", arg_comment, OPT_REQUIRED_VALUE, "string\tHuman-readable description of token"),
     OPT_STRING('x', "expire", arg_expire, OPT_REQUIRED_VALUE, "n(h|m|s)\tSet expiration time of a temporary token (default: 5m)"),
     OPT_STRING('i', "ident", arg_ident, OPT_REQUIRED_VALUE, "id\tToken ID ('*' for all tokens in zone)"),
     OPT_STRING('c', "comment", arg_comment, OPT_REQUIRED_VALUE, "string\tHuman-readable description of token"),
     OPT_STRING('x', "expire", arg_expire, OPT_REQUIRED_VALUE, "n(h|m|s)\tSet expiration time of a temporary token (default: 5m)"),
+    OPT_BOOL(0, "auth-passwd", arg_auth_passwd, 0, "\tAsk for current password to authorize the operation"),
     OPT_END
   }
 };
     OPT_END
   }
 };
index 4c70930782edd5dabaa2504a9e1fcdff03fabd85..2c50b4363dec5251ef229d6a58b9c5b182935258 100644 (file)
@@ -42,6 +42,9 @@ SubauthD {
                # Allow users to set a password
                AllowPasswd     1
 
                # Allow users to set a password
                AllowPasswd     1
 
+               # Allow users to manage account without shell access
+               AllowPasswdAuth 0
+
                # Allow users to create a token, set maximum number of tokens per user
                AllowTokens     16
 
                # Allow users to create a token, set maximum number of tokens per user
                AllowTokens     16
 
index 2205c2e9e52a0ca5e5ce7d368b7b03683debb7fc..257b560ce2c39726a95743a98f33a8afad48fa16 100644 (file)
@@ -264,6 +264,11 @@ static void db_parse_user(struct json_node *ju)
        die("Database defines accounts in zone %s, which is not configured", zone_name);
       clist_init(&aa->tokens);
 
        die("Database defines accounts in zone %s, which is not configured", zone_name);
       clist_init(&aa->tokens);
 
+      uint allow_passwd_auth;
+      if (!get_uint(ja, "p", &allow_passwd_auth))
+       allow_passwd_auth = 0;
+      aa->allow_passwd_auth = allow_passwd_auth;
+
       struct json_node **jts = get_array(ja, "t");
       if (jts)
        {
       struct json_node **jts = get_array(ja, "t");
       if (jts)
        {
@@ -375,6 +380,7 @@ void db_write(void)
          struct json_node *ja = json_new_object(js);
          json_array_append(jas, ja);
          json_object_set(ja, "z", json_new_string_ref(js, aa->zone->name));
          struct json_node *ja = json_new_object(js);
          json_array_append(jas, ja);
          json_object_set(ja, "z", json_new_string_ref(js, aa->zone->name));
+         json_object_set(ja, "p", json_new_number(js, aa->allow_passwd_auth));
          struct json_node *jts = json_new_array(js);
          CLIST_FOR_EACH(struct auth_token *, at, aa->tokens)
            {
          struct json_node *jts = json_new_array(js);
          CLIST_FOR_EACH(struct auth_token *, at, aa->tokens)
            {
index 8959d078c8d94e52871e5b28c646be9bfbc0d43f..45873eda3b3ed48ba625c71c9508a82313b3ffa5 100644 (file)
@@ -91,6 +91,14 @@ static const char *cmd_need_string(struct client *c, const char *key)
   return val;
 }
 
   return val;
 }
 
+static uint cmd_need_uint(struct client *c, const char *key)
+{
+  uint val = 0;
+  if (!get_uint(c->request, key, &val))
+    cmd_error(c, "Missing %s", key);
+  return val;
+}
+
 static struct auth_zone *cmd_need_zone(struct client *c)
 {
   const char *name = cmd_need_string(c, "zone");
 static struct auth_zone *cmd_need_zone(struct client *c)
 {
   const char *name = cmd_need_string(c, "zone");
@@ -128,8 +136,64 @@ static const char *cmd_need_target_login(struct client *c)
     }
 }
 
     }
 }
 
+static void cmd_passwd_auth_fake(struct client *c, const char *passwd)
+{
+  auth_check_token(auth_fake_token, passwd);
+  cmd_error(c, "Invalid password");
+}
+
+static struct auth_acct *cmd_need_passwd_auth_acct(struct client *c, const char *passwd)
+{
+  struct auth_zone *az = cmd_need_zone(c);
+  const char *login = cmd_need_string(c, "login");
+  if (!az->allow_passwd_auth || !az->allow_passwd)
+    {
+      msg(L_INFO, "Password authentication denied by zone configuration: login=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+      cmd_error(c, "This zone does not allow password authentication for management");
+    }
+
+  struct auth_user *au = auth_find_user(login, 0);
+  if (!au)
+    {
+      msg(L_INFO, "Password authentication failed: No user=<%s> uid=<%u>", login, c->uid);
+      cmd_passwd_auth_fake(c, passwd);
+    }
+
+  struct auth_acct *aa = auth_find_acct(au, az, 0);
+  if (!aa)
+    {
+      msg(L_INFO, "Password authentication failed: No account user=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+      cmd_passwd_auth_fake(c, passwd);
+    }
+  if (!aa->allow_passwd_auth)
+    {
+      msg(L_INFO, "Password authentication failed: Not allowed by user=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+      cmd_passwd_auth_fake(c, passwd);
+    }
+
+  struct auth_token *at = auth_find_token_passwd(aa);
+  if (!at)
+    {
+      msg(L_INFO, "Password authentication failed: No password user=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+      cmd_passwd_auth_fake(c, passwd);
+    }
+
+  if (!auth_check_token(at, passwd))
+    {
+      msg(L_INFO, "Password authentication failed: Wrong password for user=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+      cmd_error(c, "Invalid password");
+    }
+
+  msg(L_INFO, "Password authentication successful: user=<%s> zone=<%s> uid=<%u>", login, az->name, c->uid);
+  return aa;
+}
+
 static struct auth_acct *cmd_need_target_acct(struct client *c)
 {
 static struct auth_acct *cmd_need_target_acct(struct client *c)
 {
+  const char *auth_passwd = get_string(c->request, "auth-passwd");
+  if (auth_passwd)
+    return cmd_need_passwd_auth_acct(c, auth_passwd);
+
   const char *login = cmd_need_target_login(c);
   struct auth_zone *az = cmd_need_zone(c);
 
   const char *login = cmd_need_target_login(c);
   struct auth_zone *az = cmd_need_zone(c);
 
@@ -453,6 +517,21 @@ static void cmd_login(struct client *c)
   cmd_ok(c);
 }
 
   cmd_ok(c);
 }
 
+static void cmd_allow_passwd_auth(struct client *c)
+{
+  struct auth_acct *aa = cmd_need_target_acct(c);
+  uint allow = cmd_need_uint(c, "allow");
+  if (!aa->zone->allow_passwd_auth)
+    cmd_error(c, "This zone does not allow password authentication for management");
+
+  msg(L_INFO, "Setting account password authentication: allow-passwd-auth=<%u> login=<%s> zone=<%s>", !!allow, aa->user->login, aa->zone->name);
+
+  aa->allow_passwd_auth = !!allow;
+
+  db_write();
+  cmd_ok(c);
+}
+
 static void cmd_list_accts(struct client *c)
 {
   const char *login = cmd_need_target_login(c);
 static void cmd_list_accts(struct client *c)
 {
   const char *login = cmd_need_target_login(c);
@@ -474,6 +553,7 @@ static void cmd_list_accts(struct client *c)
       struct json_node *ja = json_new_object(js);
       json_array_append(jas, ja);
       set_string(c, ja, "zone", aa->zone->name);
       struct json_node *ja = json_new_object(js);
       json_array_append(jas, ja);
       set_string(c, ja, "zone", aa->zone->name);
+      set_uint(c, ja, "allow-passwd-auth", aa->zone->allow_passwd_auth && aa->allow_passwd_auth);
 
       struct json_node *jts = json_new_array(js);
       json_object_set(ja, "tokens", jts);
 
       struct json_node *jts = json_new_array(js);
       json_object_set(ja, "tokens", jts);
@@ -516,6 +596,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_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, "allow-passwd-auth", az->allow_passwd_auth);
       set_uint(c, jz, "max-temp-validity", az->max_temp_validity);
     }
 
       set_uint(c, jz, "max-temp-validity", az->max_temp_validity);
     }
 
@@ -528,18 +609,19 @@ struct command {
 };
 
 static const struct command command_table[] = {
 };
 
 static const struct command command_table[] = {
-  { "nop",             cmd_nop },
-  { "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 },
+  { "nop",                     cmd_nop },
+  { "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 },
+  { "allow-passwd-auth",       cmd_allow_passwd_auth },
+  { "list-accts",              cmd_list_accts },
+  { "list-zones",              cmd_list_zones },
 };
 
 void cmd_dispatch(struct client *c)
 };
 
 void cmd_dispatch(struct client *c)
index a8576123df292cee4c8e2068b5ef7c2fb05a3dcf..31753c97a98dafbbfaeaed417c82df01832f9298 100644 (file)
@@ -324,6 +324,7 @@ static struct cf_section zone_config = {
     CF_STRING("Description", PTR_TO(struct auth_zone, desc)),
     CF_UINT("AutoCreateAcct", PTR_TO(struct auth_zone, auto_create_acct)),
     CF_UINT("AllowPasswd", PTR_TO(struct auth_zone, allow_passwd)),
     CF_STRING("Description", PTR_TO(struct auth_zone, desc)),
     CF_UINT("AutoCreateAcct", PTR_TO(struct auth_zone, auto_create_acct)),
     CF_UINT("AllowPasswd", PTR_TO(struct auth_zone, allow_passwd)),
+    CF_UINT("AllowPasswdAuth", PTR_TO(struct auth_zone, allow_passwd_auth)),
     CF_UINT("AllowTokens", PTR_TO(struct auth_zone, allow_tokens)),
     CF_UINT("MaxTempValidity", PTR_TO(struct auth_zone, max_temp_validity)),
     CF_END
     CF_UINT("AllowTokens", PTR_TO(struct auth_zone, allow_tokens)),
     CF_UINT("MaxTempValidity", PTR_TO(struct auth_zone, max_temp_validity)),
     CF_END
index a2ca09957f0ec95c30d5690f288752d0927dbe28..3af859a47dd3eb249bf2447b47c6030c1f3ede70 100644 (file)
@@ -56,6 +56,7 @@ struct auth_zone {
   uint auto_create_acct;
   uint allow_passwd;
   uint allow_tokens;
   uint auto_create_acct;
   uint allow_passwd;
   uint allow_tokens;
+  uint allow_passwd_auth;
   uint max_temp_validity;
 };
 
   uint max_temp_validity;
 };
 
@@ -69,6 +70,7 @@ struct auth_acct {
   struct auth_user *user;
   struct auth_zone *zone;
   clist tokens;                                // of struct auth_token
   struct auth_user *user;
   struct auth_zone *zone;
   clist tokens;                                // of struct auth_token
+  uint allow_passwd_auth;
 };
 
 enum token_type {
 };
 
 enum token_type {