aboutsummaryrefslogtreecommitdiff
path: root/src/ctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/ctl.c')
-rw-r--r--src/ctl.c291
1 files changed, 198 insertions, 93 deletions
diff --git a/src/ctl.c b/src/ctl.c
index 20c16e1..f422e4b 100644
--- a/src/ctl.c
+++ b/src/ctl.c
@@ -104,8 +104,11 @@ ctlbuf_chomp (struct ctlbuf *buf)
#define CTL_END_STATE 0
#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)
struct ctlio;
@@ -152,9 +155,9 @@ static struct ctlio_command cmdtab[] = {
{ "restart", "restart component",
CTL_AUTHENTICATED_STATE, 2, 2, cmd_restart },
{ "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 }
};
@@ -190,7 +193,7 @@ ctlio_create (void)
io = xmalloc (sizeof (*io));
io->state = identity_provider_list
- ? CTL_INITIAL_STATE : CTL_AUTHENTICATED_STATE;
+ ? CTL_INITIAL_STATE : CTL_ADMIN_STATE;
io->action = ACTION_CONT;
ctlbuf_init (&io->ibuf);
ctlbuf_init (&io->obuf);
@@ -321,12 +324,42 @@ ctlio_initial_reply (struct ctlio *io)
ctlio_eol (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
cmd_auth (struct ctlio *io, size_t argc, char **argv)
{
struct grecs_list_entry *ep;
pies_identity_t id = pies_identity_create (argv[1]);
- int auth = 0;
+ int new_state = CTL_INITIAL_STATE;
for (ep = identity_provider_list->head; ep; ep = ep->next)
{
@@ -336,33 +369,54 @@ cmd_auth (struct ctlio *io, size_t argc, char **argv)
debug(1, ("trying %s...", pname));
if (pies_authenticate (provider, id, argv[2]) == 0)
{
- 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);
+ }
}
break;
}
}
- 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");
}
else
{
- pies_identity_destroy (id);
- ctlio_reply (io, "531", "access denied");
+ ctlio_reply (io, "230", "authentication successful");
+ identity = id;
+ io->state = new_state;
}
}
@@ -801,67 +855,100 @@ pcond_parse (struct ctlio *io, size_t argc, char **argv,
return 0;
}
+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
{
struct ctlio *io;
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;
}
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;
}
@@ -869,24 +956,27 @@ static void
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");
}
else
ctlio_reply (io, "552", "No match");
pcond_free (env.cond);
+ grecs_list_free (env.list);
}
static void
@@ -894,19 +984,24 @@ cmd_start (struct ctlio *io, size_t argc, char **argv)
{
char const *tag = argv[1];
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");
}
static void
@@ -914,16 +1009,21 @@ cmd_stop (struct ctlio *io, size_t argc, char **argv)
{
char const *tag = argv[1];
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");
}
static void
@@ -931,17 +1031,22 @@ cmd_restart (struct ctlio *io, size_t argc, char **argv)
{
char const *tag = argv[1];
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");
}
static void

Return to:

Send suggestions and report system problems to the System administrator.