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();
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);
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("");
enum command {
CMD_SET_PASSWD,
CMD_LIST,
+ CMD_ZONES,
CMD_RAW,
CMD_MAX
};
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,
};
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:"),
#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)
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);
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);
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);
{
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);
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);
{ "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)
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;
}
}
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;
}