From 1d8c98aa7dcc16f859a9bc7499f3bc5897bc44e8 Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Wed, 19 Jul 2017 21:05:01 +0200 Subject: [PATCH] Listing of zones --- client/subauth.c | 46 +++++++++++++++++++++++++++++------- server/cmd.c | 60 +++++++++++++++++++++++++++++++++++------------ server/subauthd.c | 1 + server/subauthd.h | 1 + 4 files changed, 84 insertions(+), 24 deletions(-) diff --git a/client/subauth.c b/client/subauth.c index dc28cd0..30dd28c 100644 --- a/client/subauth.c +++ b/client/subauth.c @@ -36,19 +36,22 @@ static void set_string(struct json_node *n, const char *key, const char *val) json_object_set(n, key, json_new_string(js, val)); } -static struct json_node *get_child(struct json_node *obj, const char *key, bool mandatory, uint type) +static struct json_node *get_child(struct json_node *obj, const char *key, uint type) { struct json_node *n = json_object_get(obj, key); - if (!n) - { - if (mandatory) - die("Malformed reply: missing %s", key); - } - else if (n->type != type) + if (n && n->type != type) die("Malformed reply: %s has wrong type", key); return n; } +static struct json_node *need_child(struct json_node *obj, const char *key, uint type) +{ + struct json_node *n = get_child(obj, key, type); + if (!n) + die("Malformed reply: missing %s", key); + return n; +} + static void op_new(const char *op) { js = json_new(); @@ -108,7 +111,7 @@ static void op_run(void) if (rp->type != JSON_OBJECT) die("Malformed reply: Top-level node is not an object"); - struct json_node *err = get_child(rp, "error", 1, JSON_STRING); + struct json_node *err = need_child(rp, "error", JSON_STRING); if (strcmp(err->string, "")) { fprintf(stderr, "Error: %s\n", err->string); @@ -124,10 +127,32 @@ static void cmd_set_passwd(void) static void cmd_list(void) { - op_new("list"); + op_new("list-accts"); op_run(); } +static void cmd_zones(void) +{ + op_new("list-zones"); + op_run(); + + struct json_node **jzs = need_child(rp, "zones", JSON_ARRAY)->elements; + printf("%-16s %6s %6s %s\n", "Zone", "Passwd", "Tokens", "Description"); + for (uint i=0; i < GARY_SIZE(jzs); i++) + { + struct json_node *jz = jzs[i]; + struct json_node *jname = need_child(jz, "name", JSON_STRING); + 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); + printf("%-16s %6s %6d %s\n", + jname->string, + (jpass && jpass->number ? "yes" : "-"), + (jtokens ? (uint) jtokens->number : 0), + (jdesc ? jdesc->string : "(no description)")); + } +} + static void cmd_raw(void) { op_new(""); @@ -142,6 +167,7 @@ static void cmd_raw(void) enum command { CMD_SET_PASSWD, CMD_LIST, + CMD_ZONES, CMD_RAW, CMD_MAX }; @@ -149,6 +175,7 @@ enum command { void (* const command_handlers[CMD_MAX])(void) = { [CMD_SET_PASSWD] = cmd_set_passwd, [CMD_LIST] = cmd_list, + [CMD_ZONES] = cmd_zones, [CMD_RAW] = cmd_raw, }; @@ -169,6 +196,7 @@ static const struct opt_section options = { OPT_HELP("Commands:"), OPT_SWITCH(0, "passwd", command, CMD_SET_PASSWD, OPT_SINGLE, "\tSet password"), OPT_SWITCH(0, "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, "raw", command, CMD_RAW, OPT_SINGLE, "\tSend raw JSON command to the daemon"), OPT_HELP(""), OPT_HELP("Command options:"), diff --git a/server/cmd.c b/server/cmd.c index 180f421..4b10368 100644 --- a/server/cmd.c +++ b/server/cmd.c @@ -13,20 +13,31 @@ #include "subauthd.h" +static void set_string(struct client *c, struct json_node *n, const char *key, const char *val) +{ + if (val) + json_object_set(n, key, json_new_string(c->json, val)); +} + +static void set_uint(struct client *c, struct json_node *n, const char *key, uint val) +{ + json_object_set(n, key, json_new_number(c->json, val)); +} + static void NONRET cmd_error(struct client *c, const char *err, ...) { va_list args; char msg[1024]; va_start(args, err); vsnprintf(msg, sizeof(msg), err, args); - json_object_set(c->reply, "error", json_new_string(c->json, msg)); + set_string(c, c->reply, "error", msg); trans_throw("adhoc", NULL, "Error caught"); va_end(args); } static void cmd_ok(struct client *c) { - json_object_set(c->reply, "error", json_new_string_ref(c->json, "")); + set_string(c, c->reply, "error", ""); } const char *get_string(struct json_node *n, const char *key) @@ -237,7 +248,7 @@ static void cmd_create_token(struct client *c) struct auth_token *at = auth_create_token(aa); char *tok = auth_set_token_generated(at, get_string(c->request, "comment")); - json_object_set(c->reply, "token", json_new_string(c->json, tok)); + set_string(c, c->reply, "token", tok); xfree(tok); msg(L_INFO, "Created token: login=<%s> zone=<%s> id=<%s>", aa->user->login, aa->zone->name, at->ident); @@ -310,7 +321,7 @@ static void cmd_login(struct client *c) cmd_ok(c); } -static void cmd_list(struct client *c) +static void cmd_list_accts(struct client *c) { const char *login = cmd_need_target_login(c); @@ -319,7 +330,7 @@ static void cmd_list(struct client *c) cmd_error(c, "No such user"); struct json_context *js = c->json; - json_object_set(c->reply, "login", json_new_string(js, au->login)); + set_string(c, c->reply, "login", au->login); struct json_node *jas = json_new_array(js); json_object_set(c->reply, "accounts", jas); @@ -327,7 +338,7 @@ static void cmd_list(struct client *c) { struct json_node *ja = json_new_object(js); json_array_append(jas, ja); - json_object_set(ja, "zone", json_new_string(js, aa->zone->name)); + set_string(c, ja, "zone", aa->zone->name); struct json_node *jts = json_new_array(js); json_object_set(ja, "tokens", jts); @@ -344,19 +355,37 @@ static void cmd_list(struct client *c) case TOKEN_GENERATED: type = "token"; break; default: type = "unknown"; break; } - json_object_set(jt, "type", json_new_string(js, type)); + set_string(c, jt, "type", type); - if (at->ident) - json_object_set(jt, "ident", json_new_string(js, at->ident)); - if (at->comment) - json_object_set(jt, "comment", json_new_string(js, at->comment)); - json_object_set(jt, "lastmod", json_new_number(js, at->last_modified)); + set_string(c, jt, "ident", at->ident); + set_string(c, jt, "comment", at->comment); + set_uint(c, jt, "lastmod", at->last_modified); } } cmd_ok(c); } +static void cmd_list_zones(struct client *c) +{ + struct json_context *js = c->json; + + struct json_node *jzs = json_new_array(js); + json_object_set(c->reply, "zones", jzs); + + CLIST_FOR_EACH(struct auth_zone *, az, zone_list) + { + struct json_node *jz = json_new_object(js); + json_array_append(jzs, jz); + set_string(c, jz, "name", az->name); + 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); + } + + cmd_ok(c); +} + struct command { const char *cmd; void (*handler)(struct client *c); @@ -369,7 +398,8 @@ static const struct command command_table[] = { { "create-token", cmd_create_token }, { "set-passwd", cmd_set_passwd }, { "login", cmd_login }, - { "list", cmd_list }, + { "list-accts", cmd_list_accts }, + { "list-zones", cmd_list_zones }, }; void cmd_dispatch(struct client *c) @@ -379,7 +409,7 @@ void cmd_dispatch(struct client *c) if (rq->type != JSON_OBJECT || !(cmd = get_string(rq, "cmd"))) { - json_object_set(c->reply, "error", json_new_string_ref(c->json, "Malformed request")); + set_string(c, c->reply, "error", "Malformed request"); return; } @@ -392,7 +422,7 @@ void cmd_dispatch(struct client *c) } if (!command) { - json_object_set(c->reply, "error", json_new_string_ref(c->json, "No such command")); + set_string(c, c->reply, "error", "No such command"); return; } diff --git a/server/subauthd.c b/server/subauthd.c index c8bff03..38b8c29 100644 --- a/server/subauthd.c +++ b/server/subauthd.c @@ -289,6 +289,7 @@ static struct cf_section zone_config = { CF_COMMIT(zone_commit), CF_ITEMS { CF_STRING("Name", PTR_TO(struct auth_zone, name)), + 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("AllowTokens", PTR_TO(struct auth_zone, allow_tokens)), diff --git a/server/subauthd.h b/server/subauthd.h index 30fd016..7148bfd 100644 --- a/server/subauthd.h +++ b/server/subauthd.h @@ -49,6 +49,7 @@ struct json_node *get_object(struct json_node *n, const char *key); struct auth_zone { cnode n; char *name; + char *desc; uint auto_create_acct; uint allow_passwd; uint allow_tokens; -- 2.39.2