]> git.ipfire.org Git - thirdparty/lldpd.git/commitdiff
lldpcli: change how privileged commands are declared
authorVincent Bernat <vincent@bernat.im>
Thu, 10 Jul 2014 20:55:58 +0000 (22:55 +0200)
committerVincent Bernat <vincent@bernat.im>
Thu, 10 Jul 2014 20:55:58 +0000 (22:55 +0200)
Even when not privileged, we declare privileged commands but tag them
accordingly. We need to be careful when executing the commands to check
the new bit.

This is a preliminary change to allow a completion command to complete
privileged commands even when not privileged.

src/client/client.h
src/client/commands.c
src/client/conf.c
src/client/lldpcli.c

index 4a97fd4e7a2e657560a7ef469ecca79efd14bef9..8c306edc1fd66bc94862335fb64d1ef01b451317 100644 (file)
@@ -68,15 +68,16 @@ struct cmd_node *commands_new(
        int(*execute)(struct lldpctl_conn_t*, struct writer*,
            struct cmd_env*, void *),
        void *);
+struct cmd_node* commands_privileged(struct cmd_node *);
 void commands_free(struct cmd_node *);
 const char *cmdenv_arg(struct cmd_env*);
 const char *cmdenv_get(struct cmd_env*, const char*);
 int cmdenv_put(struct cmd_env*, const char*, const char*);
 int cmdenv_pop(struct cmd_env*, int);
 int commands_execute(struct lldpctl_conn_t *, struct writer *,
-    struct cmd_node *, int argc, const char **argv);
-char *commands_complete(struct cmd_node *, int argc, const char **argv,
-    int all);
+    struct cmd_node *, int, const char **, int);
+char *commands_complete(struct cmd_node *, int, const char **,
+    int, int);
 /* helpers */
 int cmd_check_no_env(struct cmd_env *, void *);
 int cmd_check_env(struct cmd_env *, void *);
index e18c8f13d4c4218da27365f7f85ee8f95535cd31..d1bf242baab27ad1903c682ab90357299198ece7 100644 (file)
@@ -67,6 +67,7 @@ struct cmd_node {
 
        const char *token;      /**< Token to enter this cnode */
        const char *doc;        /**< Documentation string */
+       int privileged;         /**< Privileged command? */
 
        /**
         * Function validating entry in this node. Can be @c NULL.
@@ -97,7 +98,22 @@ commands_root(void)
 }
 
 /**
- * Create a new node.
+ * Make a node accessible only to privileged users.
+ *
+ * @param node Node to change privileges
+ * @return the modified node
+ *
+ * The node is modified. It is returned to ease chaining.
+ */
+struct cmd_node*
+commands_privileged(struct cmd_node *node)
+{
+       if (node) node->privileged = 1;
+       return node;
+}
+
+/**
+ * Create a new node acessible by any user.
  *
  * @param root  The node we want to attach this node.
  * @param token Token to enter this node. Or @c NULL if no token is needed.
@@ -300,12 +316,13 @@ struct candidate_word {
  * @param argv    Array of arguments.
  * @param word    Completed word. Or NULL when no completion is required.
  * @param all     When completing, display possible completions even if only one choice is possible.
+ * @param priv    Is the current user privileged?
  * @return 0 on success, -1 otherwise.
  */
 static int
 _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
     struct cmd_node *root, int argc, const char **argv,
-    char **word, int all)
+    char **word, int all, int priv)
 {
        int n, rc = 0, completion = (word != NULL);
        int help = 0;           /* Are we asking for help? */
@@ -322,6 +339,11 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
                        log_debug("lldpctl", "argument %02d: `%s`", n, argv[n]);
        if (completion) *word = NULL;
 
+#define CAN_EXECUTE(candidate) \
+       ((!candidate->privileged || priv) && \
+           (!candidate->validate ||                    \
+               candidate->validate(&env, candidate->arg) == 1))
+
        /* When completion is in progress, we use the same algorithm than for
         * execution until we reach the cursor position. */
        struct cmd_node *current = NULL;
@@ -340,31 +362,29 @@ _commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
                            env.argp, token);
                TAILQ_FOREACH(candidate, &current->subentries, next) {
                        if (candidate->token &&
-                           !strncmp(candidate->token, token, strlen(token))) {
-                               if (!candidate->validate ||
-                                   candidate->validate(&env, candidate->arg) == 1) {
-                                       if (candidate->token &&
-                                           !strcmp(candidate->token, token)) {
-                                               /* Exact match */
-                                               best = candidate;
-                                               break;
-                                       }
-                                       if (!best) best = candidate;
-                                       else {
-                                               if (!completion)
-                                                       log_warnx("lldpctl", "ambiguous token: %s (%s or %s)",
-                                                           token, candidate->token, best->token);
-                                               rc = -1;
-                                               goto end;
-                                       }
+                           !strncmp(candidate->token, token, strlen(token)) &&
+                           CAN_EXECUTE(candidate)) {
+                               if (candidate->token &&
+                                   !strcmp(candidate->token, token)) {
+                                       /* Exact match */
+                                       best = candidate;
+                                       break;
+                               }
+                               if (!best) best = candidate;
+                               else {
+                                       if (!completion)
+                                               log_warnx("lldpctl", "ambiguous token: %s (%s or %s)",
+                                                   token, candidate->token, best->token);
+                                       rc = -1;
+                                       goto end;
                                }
                        }
                }
                if (!best) {
                        /* Take first that validate */
                        TAILQ_FOREACH(candidate, &current->subentries, next) {
-                               if (!candidate->token && (!candidate->validate ||
-                                       candidate->validate(&env, candidate->arg) == 1)) {
+                               if (!candidate->token &&
+                                   CAN_EXECUTE(candidate)) {
                                        best = candidate;
                                        break;
                                }
@@ -405,8 +425,7 @@ end:
                                if ((!candidate->token || help ||
                                        !strncmp(env.argv[env.argc - 1], candidate->token,
                                            strlen(env.argv[env.argc -1 ]))) &&
-                                   (!candidate->validate ||
-                                       candidate->validate(&env, candidate->arg) == 1)) {
+                                   CAN_EXECUTE(candidate)) {
                                        struct candidate_word *cword =
                                            malloc(sizeof(struct candidate_word));
                                        if (!cword) break;
@@ -483,11 +502,11 @@ end:
  */
 char *
 commands_complete(struct cmd_node *root, int argc, const char **argv,
-    int all)
+    int all, int privileged)
 {
        char *word = NULL;
        if (_commands_execute(NULL, NULL, root, argc, argv,
-               &word, all) == 0)
+               &word, all, privileged) == 0)
                return word;
        return NULL;
 }
@@ -497,9 +516,9 @@ commands_complete(struct cmd_node *root, int argc, const char **argv,
  */
 int
 commands_execute(struct lldpctl_conn_t *conn, struct writer *w,
-    struct cmd_node *root, int argc, const char **argv)
+    struct cmd_node *root, int argc, const char **argv, int privileged)
 {
-       return _commands_execute(conn, w, root, argc, argv, NULL, 0);
+       return _commands_execute(conn, w, root, argc, argv, NULL, 0, privileged);
 }
 
 /**
index 7e7c67a2d6f82b43a3dedcfb583a40d1417825ec..d9f0111e0cc4aa54d6503ddc34233eb2a8afbbaf 100644 (file)
@@ -37,6 +37,8 @@ register_commands_configure(struct cmd_node *root)
                "unconfigure",
                "Unconfigure system settings",
                NULL, NULL, NULL);
+       commands_privileged(configure);
+       commands_privileged(unconfigure);
        cmd_restrict_ports(configure);
        cmd_restrict_ports(unconfigure);
 
index c68cb3a66b43d57b638a2e1c52c215619cbdccc6..f96b9c57b4cbbb773c9f5551867983cb1d4ac56e 100644 (file)
@@ -206,7 +206,7 @@ _cmd_complete(int all)
        if (tokenize_line(line, &argc, &argv) != 0)
                goto end;
 
-       char *compl = commands_complete(root, argc, (const char **)argv, all);
+       char *compl = commands_complete(root, argc, (const char **)argv, all, is_privileged());
        if (compl && strlen(argv[argc-1]) < strlen(compl)) {
                if (rl_insert_text(compl + strlen(argv[argc-1])) < 0) {
                        free(compl);
@@ -278,7 +278,7 @@ cmd_exec(lldpctl_conn_t *conn, const char *fmt, int argc, const char **argv)
 
        /* Execute command */
        int rc = commands_execute(conn, w,
-           root, argc, argv);
+           root, argc, argv, is_privileged());
        if (rc != 0) {
                log_info("lldpctl", "an error occurred while executing last command");
                w->finish(w);
@@ -325,14 +325,12 @@ register_commands()
        root = commands_root();
        register_commands_show(root);
        register_commands_watch(root);
-       if (is_privileged()) {
-               commands_new(
-                       commands_new(root, "update", "Update information and send LLDPU on all ports",
-                           NULL, NULL, NULL),
-                       NEWLINE, "Update information and send LLDPU on all ports",
-                       NULL, cmd_update, NULL);
-               register_commands_configure(root);
-       }
+       commands_privileged(commands_new(
+               commands_new(root, "update", "Update information and send LLDPU on all ports",
+                   NULL, NULL, NULL),
+               NEWLINE, "Update information and send LLDPU on all ports",
+               NULL, cmd_update, NULL));
+       register_commands_configure(root);
        commands_new(root, "help", "Get help on a possible command",
            NULL, cmd_store_env_and_pop, "help");
        commands_new(