diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-17 12:50:28 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-17 12:50:28 +0200 |
commit | 8334b598f85317eb4d44000f6ec580c54734b15d (patch) | |
tree | 04dd1b84443287aec625ab019b02fc170ae524a1 /src/ctl.c | |
parent | 8426fc4411c9679a10863d7aa3ced077155e0016 (diff) | |
download | pies-8334b598f85317eb4d44000f6ec580c54734b15d.tar.gz pies-8334b598f85317eb4d44000f6ec580c54734b15d.tar.bz2 |
Implement user privileges
* src/pies.h (component): New members: list_acl and
adm_acl.
(control): Removed id_acl.
New members: adm_acl and usr_acl.
* src/pies.c (component_keywords): New keywords list-acl and
admin-acl. Removed identity-acl.
* ident/ident.c (pies_identity_user_name): New function.
* ident/identity.h (pies_identity_user_name): New proto.
* src/ctl.c (CTL_USER_STATE,CTL_ADMIN_STATE): New states.
(cmdtab): Mark administrative commands as valid in CTL_ADMIN_STATE
(ctlio_create): Assume CTL_ADMIN_STATE in the absense of identity
providers.
(auth_data): New struct.
(cmd_auth): Select appropriate state depending on the user permissions.
(list_matches): New function.
(eval_env): Keep the list of selected progs.
(count_prog): Removed.
(selector): New function.
(cmd_list): Rewrite to take into account access rights.
(cmd_start,cmd_stop)
(cmd_restart): Only allowed for users with administrative
privileges.
Diffstat (limited to 'src/ctl.c')
-rw-r--r-- | src/ctl.c | 291 |
1 files changed, 198 insertions, 93 deletions
@@ -106,4 +106,7 @@ ctlbuf_chomp (struct ctlbuf *buf) #define CTL_INITIAL_STATE 0x01 -#define CTL_AUTHENTICATED_STATE 0x02 -#define CTL_ACTION_STATE 0x04 +#define CTL_USER_STATE 0x02 +#define CTL_ADMIN_STATE 0x04 +#define CTL_ACTION_STATE 0x08 + +#define CTL_AUTHENTICATED_STATE (CTL_USER_STATE|CTL_ADMIN_STATE) #define CTL_ALL_STATES (CTL_INITIAL_STATE|CTL_AUTHENTICATED_STATE) @@ -154,5 +157,5 @@ static struct ctlio_command cmdtab[] = { { "reboot", "restart pies", - CTL_AUTHENTICATED_STATE, 1, 1, cmd_reboot }, + CTL_ADMIN_STATE, 1, 1, cmd_reboot }, { "shutdown", "stop pies", - CTL_AUTHENTICATED_STATE, 1, 1, cmd_shutdown }, + CTL_ADMIN_STATE, 1, 1, cmd_shutdown }, { NULL } @@ -192,3 +195,3 @@ ctlio_create (void) io->state = identity_provider_list - ? CTL_INITIAL_STATE : CTL_AUTHENTICATED_STATE; + ? CTL_INITIAL_STATE : CTL_ADMIN_STATE; io->action = ACTION_CONT; @@ -323,2 +326,32 @@ ctlio_initial_reply (struct ctlio *io) +struct auth_data +{ + union pies_sockaddr_storage addr; + socklen_t addrlen; + pies_identity_t id; + struct component const *comp; +}; + +static int +try_auth (struct prog *prog, void *data) +{ + struct auth_data *auth = data; + if (IS_COMPONENT (prog)) + { + if ((prog->v.p.comp->adm_acl + && check_acl (prog->v.p.comp->adm_acl, + (struct sockaddr *)&auth->addr, auth->addrlen, + auth->id) == 0) + || (prog->v.p.comp->list_acl + && check_acl (prog->v.p.comp->list_acl, + (struct sockaddr *)&auth->addr, auth->addrlen, + auth->id) == 0)) + { + auth->comp = prog->v.p.comp; + return 1; + } + } + return 0; +} + static void @@ -328,3 +361,3 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv) pies_identity_t id = pies_identity_create (argv[1]); - int auth = 0; + int new_state = CTL_INITIAL_STATE; @@ -338,14 +371,35 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv) { - if (check_acl (control.id_acl, - (struct sockaddr *)&io->addr, io->addrlen, id)) + if (control.adm_acl + && check_acl (control.adm_acl, + (struct sockaddr *)&io->addr, io->addrlen, + id) == 0) { - logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check", + new_state = CTL_ADMIN_STATE; + logmsg (LOG_AUTH, "%s granted admin access via %s", argv[1], pname); - auth = 0; } - else + else if (control.usr_acl + && check_acl (control.usr_acl, + (struct sockaddr *)&io->addr, io->addrlen, + id) == 0) { + new_state = CTL_USER_STATE; logmsg (LOG_AUTH, "%s authenticated via %s", argv[1], pname); - auth = 1; + } + else + { + struct auth_data ad = { io->addr, io->addrlen, id, NULL }; + progman_foreach (try_auth, &ad); + if (ad.comp) + { + new_state = CTL_USER_STATE; + logmsg (LOG_AUTH, "%s authenticated via %s, component %s", + argv[1], pname, ad.comp->tag); + } + else + { + logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check", + argv[1], pname); + } } @@ -355,7 +409,6 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv) - if (auth) + if (new_state == CTL_INITIAL_STATE) { - ctlio_reply (io, "230", "authentication successful"); - identity = id; - io->state = CTL_AUTHENTICATED_STATE; + pies_identity_destroy (id); + ctlio_reply (io, "531", "access denied"); } @@ -363,4 +416,5 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv) { - pies_identity_destroy (id); - ctlio_reply (io, "531", "access denied"); + ctlio_reply (io, "230", "authentication successful"); + identity = id; + io->state = new_state; } @@ -803,2 +857,53 @@ pcond_parse (struct ctlio *io, size_t argc, char **argv, +static int +list_matches (struct ctlio *io, struct grecs_list *matches) +{ + struct grecs_list_entry *ep; + size_t i; + + for (ep = matches->head; ep; ep = ep->next) + { + struct prog *prog = ep->data; + + ctlio_reply (io, "151", "%s", prog->tag); + FORMAT_IDX (io, "Type", pies_type_str, prog->type); + switch (prog->type) + { + case TYPE_COMPONENT: + FORMAT_IDX (io, "Mode", pies_comp_mode_str, prog->v.p.comp->mode); + FORMAT_IDX (io, "Status", status_str, prog->v.p.status); + + if (prog->pid) + ctlio_printf (io, "PID: %lu%s", (unsigned long) prog->pid, CRLF); + else if (prog->v.p.status == status_listener + && prog->v.p.comp->socket_url) + ctlio_printf (io, "URL: %10s%s", + prog->v.p.comp->socket_url->string, + CRLF); + + if (prog->v.p.status == status_sleeping) + { + ctlio_printf (io, "Wakeup-Time: %lu%s", + (unsigned long) (prog->v.p.timestamp + SLEEPTIME), + CRLF); + } + + ctlio_printf (io, "Command:"); + for (i = 0; i < prog->v.p.comp->argc; i++) + ctlio_printf (io, " %s", quotearg (prog->v.p.comp->argv[i])); + ctlio_eol (io); + break; + + case TYPE_REDIRECTOR: + ctlio_printf (io, "PID: %10lu%s", (unsigned long) prog->pid, CRLF); + break; + + case TYPE_COMMAND: + ctlio_printf (io, "Command: %s%s", prog->v.c.command, CRLF); + } + ctlio_eot (io); + } + return 0; +} + struct eval_env @@ -807,50 +912,31 @@ struct eval_env struct pcond_node *cond; - size_t count; + struct grecs_list *list; }; +/* Authenticate access to PROG. Return 0, CTL_USER_STATE or + CTL_ADMIN_STATE depending on whether and what kind of access is + allowed for the current identity */ static int -list_prog (struct prog *prog, void *data) +auth_prog (struct prog *prog, struct ctlio *io) { - struct eval_env *env = data; - struct ctlio *io = env->io; - size_t i; - - if (!pcond_eval (env->cond, prog)) - return 0; - ctlio_reply (io, "151", "%s", prog->tag); - FORMAT_IDX (io, "Type", pies_type_str, prog->type); + if (io->state == CTL_ADMIN_STATE) + return CTL_ADMIN_STATE|CTL_USER_STATE; switch (prog->type) { - case TYPE_COMPONENT: - FORMAT_IDX (io, "Mode", pies_comp_mode_str, prog->v.p.comp->mode); - FORMAT_IDX (io, "Status", status_str, prog->v.p.status); - - if (prog->pid) - ctlio_printf (io, "PID: %lu%s", (unsigned long) prog->pid, CRLF); - else if (prog->v.p.status == status_listener - && prog->v.p.comp->socket_url) - ctlio_printf (io, "URL: %10s%s", prog->v.p.comp->socket_url->string, - CRLF); - - if (prog->v.p.status == status_sleeping) - { - ctlio_printf (io, "Wakeup-Time: %lu%s", - (unsigned long) (prog->v.p.timestamp + SLEEPTIME), - CRLF); - } - - ctlio_printf (io, "Command:"); - for (i = 0; i < prog->v.p.comp->argc; i++) - ctlio_printf (io, " %s", quotearg (prog->v.p.comp->argv[i])); - ctlio_eol (io); - break; - case TYPE_REDIRECTOR: - ctlio_printf (io, "PID: %10lu%s", (unsigned long) prog->pid, CRLF); + prog = prog->v.r.master; + /* FALL THROUGH */ + case TYPE_COMPONENT: + if (prog->v.p.comp->adm_acl + && check_acl (prog->v.p.comp->adm_acl, + (struct sockaddr *)&io->addr, io->addrlen, + identity) == 0) + return CTL_ADMIN_STATE; + if (check_acl (prog->v.p.comp->list_acl, + (struct sockaddr *)&io->addr, io->addrlen, + identity) == 0) + return CTL_USER_STATE; + default: break; - - case TYPE_COMMAND: - ctlio_printf (io, "Command: %s%s", prog->v.c.command, CRLF); } - ctlio_eot (io); return 0; @@ -859,7 +945,8 @@ list_prog (struct prog *prog, void *data) static int -count_prog (struct prog *prog, void *data) +selector (struct prog *prog, void *data) { struct eval_env *env = data; - if (pcond_eval (env->cond, prog)) - ++env->count; + + if (pcond_eval (env->cond, prog) && auth_prog (prog, env->io)) + grecs_list_append (env->list, prog); return 0; @@ -871,14 +958,16 @@ cmd_list (struct ctlio *io, size_t argc, char **argv) struct eval_env env; + size_t size; env.io = io; - env.count = 0; if (pcond_parse (io, argc - 1, argv + 1, &env.cond)) return; + env.list = grecs_list_create (); - progman_foreach (count_prog, &env); - if (env.count) + progman_foreach (selector, &env); + size = grecs_list_size (env.list); + if (size) { ctlio_reply (io, "150", "%lu matches found; list follows", - env.count); - progman_foreach (list_prog, &env); + (unsigned long) size); + list_matches (io, env.list); ctlio_reply (io, "250", "complete"); @@ -889,2 +978,3 @@ cmd_list (struct ctlio *io, size_t argc, char **argv) pcond_free (env.cond); + grecs_list_free (env.list); } @@ -896,15 +986,20 @@ cmd_start (struct ctlio *io, size_t argc, char **argv) struct prog *prog = progman_locate (tag); - if (!prog) - ctlio_reply (io, "552", "Component not found"); - else if (!IS_COMPONENT (prog)) - ctlio_reply (io, "553", "Not a component"); - else if (prog->v.p.status != status_disabled) - ctlio_reply (io, "554", "Not stopped"); - else + if (auth_prog (prog, io) & CTL_ADMIN_STATE) { - prog->v.p.comp->flags &= CF_DISABLED; - prog->v.p.status = status_enabled; - kill (getpid (), SIGALRM); - ctlio_reply (io, "250", "Complete"); + if (!prog) + ctlio_reply (io, "552", "Component not found"); + else if (!IS_COMPONENT (prog)) + ctlio_reply (io, "553", "Not a component"); + else if (prog->v.p.status != status_disabled) + ctlio_reply (io, "554", "Not stopped"); + else + { + prog->v.p.comp->flags &= CF_DISABLED; + prog->v.p.status = status_enabled; + kill (getpid (), SIGALRM); + ctlio_reply (io, "250", "Complete"); + } } + else + ctlio_reply (io, "531", "access denied"); } @@ -916,12 +1011,17 @@ cmd_stop (struct ctlio *io, size_t argc, char **argv) struct prog *prog = progman_locate (tag); - if (!prog) - ctlio_reply (io, "552", "Component not found"); - else if (!IS_COMPONENT (prog)) - ctlio_reply (io, "553", "Not a component"); - else + if (auth_prog (prog, io) & CTL_ADMIN_STATE) { - progman_stop_component (prog); - prog->v.p.comp->flags |= CF_DISABLED; - ctlio_reply (io, "250", "Complete"); + if (!prog) + ctlio_reply (io, "552", "Component not found"); + else if (!IS_COMPONENT (prog)) + ctlio_reply (io, "553", "Not a component"); + else + { + progman_stop_component (prog); + prog->v.p.comp->flags |= CF_DISABLED; + ctlio_reply (io, "250", "Complete"); + } } + else + ctlio_reply (io, "531", "access denied"); } @@ -933,13 +1033,18 @@ cmd_restart (struct ctlio *io, size_t argc, char **argv) struct prog *prog = progman_locate (tag); - if (!prog) - ctlio_reply (io, "552", "Component not found"); - else if (!(IS_COMPONENT (prog) - && !(prog->v.p.comp->mode == pies_comp_inetd - && prog->v.p.listener))) - ctlio_reply (io, "553", "Not a component"); - else + if (auth_prog (prog, io) & CTL_ADMIN_STATE) { - progman_stop_component (prog); - ctlio_reply (io, "250", "Complete"); + if (!prog) + ctlio_reply (io, "552", "Component not found"); + else if (!(IS_COMPONENT (prog) + && !(prog->v.p.comp->mode == pies_comp_inetd + && prog->v.p.listener))) + ctlio_reply (io, "553", "Not a component"); + else + { + progman_stop_component (prog); + ctlio_reply (io, "250", "Complete"); + } } + else + ctlio_reply (io, "531", "access denied"); } |