2 * Sub-authentication Daemon: Commands
4 * (c) 2017 Martin Mares <mj@ucw.cz>
16 static void NONRET cmd_error(struct client *c, const char *err, ...)
21 vsnprintf(msg, sizeof(msg), err, args);
22 json_object_set(c->reply, "error", json_new_string(c->json, msg));
23 trans_throw("adhoc", NULL, "Error caught");
27 static void cmd_ok(struct client *c)
29 json_object_set(c->reply, "error", json_new_string_ref(c->json, ""));
32 const char *get_string(struct json_node *n, const char *key)
34 struct json_node *s = json_object_get(n, key);
35 if (s && s->type == JSON_STRING)
41 bool get_uint(struct json_node *n, const char *key, uint *dest)
43 struct json_node *s = json_object_get(n, key);
44 if (s && s->type == JSON_NUMBER)
46 uint u = (uint) s->number;
47 if ((double) u == s->number)
57 struct json_node **get_array(struct json_node *n, const char *key)
59 struct json_node *s = json_object_get(n, key);
60 if (s && s->type == JSON_ARRAY)
66 struct json_node *get_object(struct json_node *n, const char *key)
68 struct json_node *s = json_object_get(n, key);
69 if (s && s->type == JSON_OBJECT)
75 static const char *cmd_need_string(struct client *c, const char *key)
77 const char *val = get_string(c->request, key);
79 cmd_error(c, "Missing %s", key);
83 static struct auth_zone *cmd_need_zone(struct client *c)
85 const char *name = cmd_need_string(c, "zone");
86 struct auth_zone *az = auth_find_zone(name);
88 cmd_error(c, "No such zone");
92 static bool cmd_is_admin(struct client *c)
99 static void cmd_require_admin(struct client *c)
101 if (!cmd_is_admin(c))
102 cmd_error(c, "Permission denied");
105 static const char *cmd_need_target_login(struct client *c)
107 const char *l = get_string(c->request, "login");
110 cmd_require_admin(c);
115 struct passwd *pw = getpwuid(c->uid);
117 cmd_error(c, "You do not exist");
118 return json_strdup(c->json, pw->pw_name);
122 static struct auth_acct *cmd_need_target_acct(struct client *c)
124 const char *login = cmd_need_target_login(c);
125 struct auth_zone *az = cmd_need_zone(c);
127 struct auth_user *au = auth_find_user(login, 0);
128 struct auth_acct *aa = au ? auth_find_acct(au, az, 0) : NULL;
132 if (!az->auto_create_acct)
133 cmd_error(c, "No such account");
137 msg(L_INFO, "Automatically creating user: login=<%s>", login);
138 au = auth_find_user(login, 1);
140 msg(L_INFO, "Automatically creating account: login=<%s> zone=<%s>", login, az->name);
141 return auth_find_acct(au, az, 1);
144 static void cmd_nop(struct client *c)
149 static void cmd_create_acct(struct client *c)
151 cmd_require_admin(c);
153 const char *login = get_string(c->request, "login");
155 cmd_error(c, "Login required");
157 struct auth_zone *az = cmd_need_zone(c);
158 struct auth_user *au = auth_find_user(login, 1);
159 if (!auth_find_acct(au, az, 0))
161 msg(L_INFO, "Creating account: login=<%s> zone=<%s>", login, az->name);
162 auth_find_acct(au, az, 1);
169 static void cmd_delete_acct(struct client *c)
171 cmd_require_admin(c);
173 const char *login = get_string(c->request, "login");
175 cmd_error(c, "Login required");
176 const char *zone_name = get_string(c->request, "zone");
178 struct auth_user *au = auth_find_user(login, 0);
182 if (zone_name && !strcmp(zone_name, "*"))
184 msg(L_INFO, "Deleting user: login=<%s>", login);
185 auth_delete_user(au);
189 struct auth_zone *az = cmd_need_zone(c);
190 struct auth_acct *aa = auth_find_acct(au, az, 0);
193 msg(L_INFO, "Deleting account: login=<%s> zone=<%s>", login, az->name);
194 auth_delete_acct(aa);
195 if (!clist_head(&au->accounts))
197 msg(L_INFO, "Deleting user with no accounts: login=<%s>", login);
198 auth_delete_user(au);
206 static void cmd_set_passwd(struct client *c)
208 struct auth_acct *aa = cmd_need_target_acct(c);
209 const char *passwd = cmd_need_string(c, "passwd");
211 if (!aa->zone->allow_passwd)
212 cmd_error(c, "This zone does not allow authentication by password");
214 msg(L_INFO, "Set password: login=<%s> zone=<%s>", aa->user->login, aa->zone->name);
216 CLIST_FOR_EACH(struct auth_token *, at, aa->tokens)
217 if (at->type == TOKEN_PASSWORD)
219 auth_delete_token(at);
223 struct auth_token *at = auth_create_token(aa);
224 auth_set_token_passwd(at, passwd);
232 static void cmd_verify(struct client *c)
234 struct auth_acct *aa = cmd_need_target_acct(c);
235 const char *passwd = cmd_need_string(c, "passwd");
244 void (*handler)(struct client *c);
247 static const struct command command_table[] = {
249 { "create-acct", cmd_create_acct },
250 { "delete-acct", cmd_delete_acct },
251 { "set-passwd", cmd_set_passwd },
252 { "verify", cmd_verify },
255 void cmd_dispatch(struct client *c)
257 struct json_node *rq = c->request;
260 if (rq->type != JSON_OBJECT || !(cmd = get_string(rq, "cmd")))
262 json_object_set(c->reply, "error", json_new_string_ref(c->json, "Malformed request"));
266 const struct command *command = NULL;
267 for (uint i=0; i < ARRAY_SIZE(command_table); i++)
268 if (!strcmp(cmd, command_table[i].cmd))
270 command = &command_table[i];
275 json_object_set(c->reply, "error", json_new_string_ref(c->json, "No such command"));