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
@@ -104,8 +104,11 @@ ctlbuf_chomp (struct ctlbuf *buf) | |||
104 | 104 | ||
105 | #define CTL_END_STATE 0 | 105 | #define CTL_END_STATE 0 |
106 | #define CTL_INITIAL_STATE 0x01 | 106 | #define CTL_INITIAL_STATE 0x01 |
107 | #define CTL_AUTHENTICATED_STATE 0x02 | 107 | #define CTL_USER_STATE 0x02 |
108 | #define CTL_ACTION_STATE 0x04 | 108 | #define CTL_ADMIN_STATE 0x04 |
109 | #define CTL_ACTION_STATE 0x08 | ||
110 | |||
111 | #define CTL_AUTHENTICATED_STATE (CTL_USER_STATE|CTL_ADMIN_STATE) | ||
109 | #define CTL_ALL_STATES (CTL_INITIAL_STATE|CTL_AUTHENTICATED_STATE) | 112 | #define CTL_ALL_STATES (CTL_INITIAL_STATE|CTL_AUTHENTICATED_STATE) |
110 | 113 | ||
111 | struct ctlio; | 114 | struct ctlio; |
@@ -152,9 +155,9 @@ static struct ctlio_command cmdtab[] = { | |||
152 | { "restart", "restart component", | 155 | { "restart", "restart component", |
153 | CTL_AUTHENTICATED_STATE, 2, 2, cmd_restart }, | 156 | CTL_AUTHENTICATED_STATE, 2, 2, cmd_restart }, |
154 | { "reboot", "restart pies", | 157 | { "reboot", "restart pies", |
155 | CTL_AUTHENTICATED_STATE, 1, 1, cmd_reboot }, | 158 | CTL_ADMIN_STATE, 1, 1, cmd_reboot }, |
156 | { "shutdown", "stop pies", | 159 | { "shutdown", "stop pies", |
157 | CTL_AUTHENTICATED_STATE, 1, 1, cmd_shutdown }, | 160 | CTL_ADMIN_STATE, 1, 1, cmd_shutdown }, |
158 | { NULL } | 161 | { NULL } |
159 | }; | 162 | }; |
160 | 163 | ||
@@ -190,7 +193,7 @@ ctlio_create (void) | |||
190 | 193 | ||
191 | io = xmalloc (sizeof (*io)); | 194 | io = xmalloc (sizeof (*io)); |
192 | io->state = identity_provider_list | 195 | io->state = identity_provider_list |
193 | ? CTL_INITIAL_STATE : CTL_AUTHENTICATED_STATE; | 196 | ? CTL_INITIAL_STATE : CTL_ADMIN_STATE; |
194 | io->action = ACTION_CONT; | 197 | io->action = ACTION_CONT; |
195 | ctlbuf_init (&io->ibuf); | 198 | ctlbuf_init (&io->ibuf); |
196 | ctlbuf_init (&io->obuf); | 199 | ctlbuf_init (&io->obuf); |
@@ -321,12 +324,42 @@ ctlio_initial_reply (struct ctlio *io) | |||
321 | ctlio_eol (io); | 324 | ctlio_eol (io); |
322 | } | 325 | } |
323 | 326 | ||
327 | struct auth_data | ||
328 | { | ||
329 | union pies_sockaddr_storage addr; | ||
330 | socklen_t addrlen; | ||
331 | pies_identity_t id; | ||
332 | struct component const *comp; | ||
333 | }; | ||
334 | |||
335 | static int | ||
336 | try_auth (struct prog *prog, void *data) | ||
337 | { | ||
338 | struct auth_data *auth = data; | ||
339 | if (IS_COMPONENT (prog)) | ||
340 | { | ||
341 | if ((prog->v.p.comp->adm_acl | ||
342 | && check_acl (prog->v.p.comp->adm_acl, | ||
343 | (struct sockaddr *)&auth->addr, auth->addrlen, | ||
344 | auth->id) == 0) | ||
345 | || (prog->v.p.comp->list_acl | ||
346 | && check_acl (prog->v.p.comp->list_acl, | ||
347 | (struct sockaddr *)&auth->addr, auth->addrlen, | ||
348 | auth->id) == 0)) | ||
349 | { | ||
350 | auth->comp = prog->v.p.comp; | ||
351 | return 1; | ||
352 | } | ||
353 | } | ||
354 | return 0; | ||
355 | } | ||
356 | |||
324 | static void | 357 | static void |
325 | cmd_auth (struct ctlio *io, size_t argc, char **argv) | 358 | cmd_auth (struct ctlio *io, size_t argc, char **argv) |
326 | { | 359 | { |
327 | struct grecs_list_entry *ep; | 360 | struct grecs_list_entry *ep; |
328 | pies_identity_t id = pies_identity_create (argv[1]); | 361 | pies_identity_t id = pies_identity_create (argv[1]); |
329 | int auth = 0; | 362 | int new_state = CTL_INITIAL_STATE; |
330 | 363 | ||
331 | for (ep = identity_provider_list->head; ep; ep = ep->next) | 364 | for (ep = identity_provider_list->head; ep; ep = ep->next) |
332 | { | 365 | { |
@@ -336,33 +369,54 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv) | |||
336 | debug(1, ("trying %s...", pname)); | 369 | debug(1, ("trying %s...", pname)); |
337 | if (pies_authenticate (provider, id, argv[2]) == 0) | 370 | if (pies_authenticate (provider, id, argv[2]) == 0) |
338 | { | 371 | { |
339 | if (check_acl (control.id_acl, | 372 | if (control.adm_acl |
340 | (struct sockaddr *)&io->addr, io->addrlen, id)) | 373 | && check_acl (control.adm_acl, |
374 | (struct sockaddr *)&io->addr, io->addrlen, | ||
375 | id) == 0) | ||
341 | { | 376 | { |
342 | logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check", | 377 | new_state = CTL_ADMIN_STATE; |
378 | logmsg (LOG_AUTH, "%s granted admin access via %s", | ||
343 | argv[1], pname); | 379 | argv[1], pname); |
344 | auth = 0; | ||
345 | } | 380 | } |
346 | else | 381 | else if (control.usr_acl |
382 | && check_acl (control.usr_acl, | ||
383 | (struct sockaddr *)&io->addr, io->addrlen, | ||
384 | id) == 0) | ||
347 | { | 385 | { |
386 | new_state = CTL_USER_STATE; | ||
348 | logmsg (LOG_AUTH, "%s authenticated via %s", | 387 | logmsg (LOG_AUTH, "%s authenticated via %s", |
349 | argv[1], pname); | 388 | argv[1], pname); |
350 | auth = 1; | 389 | } |
390 | else | ||
391 | { | ||
392 | struct auth_data ad = { io->addr, io->addrlen, id, NULL }; | ||
393 | progman_foreach (try_auth, &ad); | ||
394 | if (ad.comp) | ||
395 | { | ||
396 | new_state = CTL_USER_STATE; | ||
397 | logmsg (LOG_AUTH, "%s authenticated via %s, component %s", | ||
398 | argv[1], pname, ad.comp->tag); | ||
399 | } | ||
400 | else | ||
401 | { | ||
402 | logmsg (LOG_AUTH, "%s authenticated via %s, but failed ACL check", | ||
403 | argv[1], pname); | ||
404 | } | ||
351 | } | 405 | } |
352 | break; | 406 | break; |
353 | } | 407 | } |
354 | } | 408 | } |
355 | 409 | ||
356 | if (auth) | 410 | if (new_state == CTL_INITIAL_STATE) |
357 | { | 411 | { |
358 | ctlio_reply (io, "230", "authentication successful"); | 412 | pies_identity_destroy (id); |
359 | identity = id; | 413 | ctlio_reply (io, "531", "access denied"); |
360 | io->state = CTL_AUTHENTICATED_STATE; | ||
361 | } | 414 | } |
362 | else | 415 | else |
363 | { | 416 | { |
364 | pies_identity_destroy (id); | 417 | ctlio_reply (io, "230", "authentication successful"); |
365 | ctlio_reply (io, "531", "access denied"); | 418 | identity = id; |
419 | io->state = new_state; | ||
366 | } | 420 | } |
367 | } | 421 | } |
368 | 422 | ||
@@ -801,67 +855,100 @@ pcond_parse (struct ctlio *io, size_t argc, char **argv, | |||
801 | return 0; | 855 | return 0; |
802 | } | 856 | } |
803 | 857 | ||
858 | static int | ||
859 | list_matches (struct ctlio *io, struct grecs_list *matches) | ||
860 | { | ||
861 | struct grecs_list_entry *ep; | ||
862 | size_t i; | ||
863 | |||
864 | for (ep = matches->head; ep; ep = ep->next) | ||
865 | { | ||
866 | struct prog *prog = ep->data; | ||
867 | |||
868 | ctlio_reply (io, "151", "%s", prog->tag); | ||
869 | FORMAT_IDX (io, "Type", pies_type_str, prog->type); | ||
870 | switch (prog->type) | ||
871 | { | ||
872 | case TYPE_COMPONENT: | ||
873 | FORMAT_IDX (io, "Mode", pies_comp_mode_str, prog->v.p.comp->mode); | ||
874 | FORMAT_IDX (io, "Status", status_str, prog->v.p.status); | ||
875 | |||
876 | if (prog->pid) | ||
877 | ctlio_printf (io, "PID: %lu%s", (unsigned long) prog->pid, CRLF); | ||
878 | else if (prog->v.p.status == status_listener | ||
879 | && prog->v.p.comp->socket_url) | ||
880 | ctlio_printf (io, "URL: %10s%s", | ||
881 | prog->v.p.comp->socket_url->string, | ||
882 | CRLF); | ||
883 | |||
884 | if (prog->v.p.status == status_sleeping) | ||
885 | { | ||
886 | ctlio_printf (io, "Wakeup-Time: %lu%s", | ||
887 | (unsigned long) (prog->v.p.timestamp + SLEEPTIME), | ||
888 | CRLF); | ||
889 | } | ||
890 | |||
891 | ctlio_printf (io, "Command:"); | ||
892 | for (i = 0; i < prog->v.p.comp->argc; i++) | ||
893 | ctlio_printf (io, " %s", quotearg (prog->v.p.comp->argv[i])); | ||
894 | ctlio_eol (io); | ||
895 | break; | ||
896 | |||
897 | case TYPE_REDIRECTOR: | ||
898 | ctlio_printf (io, "PID: %10lu%s", (unsigned long) prog->pid, CRLF); | ||
899 | break; | ||
900 | |||
901 | case TYPE_COMMAND: | ||
902 | ctlio_printf (io, "Command: %s%s", prog->v.c.command, CRLF); | ||
903 | } | ||
904 | ctlio_eot (io); | ||
905 | } | ||
906 | return 0; | ||
907 | } | ||
908 | |||
804 | struct eval_env | 909 | struct eval_env |
805 | { | 910 | { |
806 | struct ctlio *io; | 911 | struct ctlio *io; |
807 | struct pcond_node *cond; | 912 | struct pcond_node *cond; |
808 | size_t count; | 913 | struct grecs_list *list; |
809 | }; | 914 | }; |
810 | 915 | ||
916 | /* Authenticate access to PROG. Return 0, CTL_USER_STATE or | ||
917 | CTL_ADMIN_STATE depending on whether and what kind of access is | ||
918 | allowed for the current identity */ | ||
811 | static int | 919 | static int |
812 | list_prog (struct prog *prog, void *data) | 920 | auth_prog (struct prog *prog, struct ctlio *io) |
813 | { | 921 | { |
814 | struct eval_env *env = data; | 922 | if (io->state == CTL_ADMIN_STATE) |
815 | struct ctlio *io = env->io; | 923 | return CTL_ADMIN_STATE|CTL_USER_STATE; |
816 | size_t i; |