"Fossies" - the Fresh Open Source Software Archive

Member "sudo-1.9.11p3/plugins/sudoers/check_aliases.c" (12 Jun 2022, 6421 Bytes) of package /linux/misc/sudo-1.9.11p3.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "check_aliases.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 1.9.10_vs_1.9.11rc1.

    1 /*
    2  * SPDX-License-Identifier: ISC
    3  *
    4  * Copyright (c) 2004-2005, 2007-2018, 2021-2022
    5  *  Todd C. Miller <Todd.Miller@sudo.ws>
    6  *
    7  * Permission to use, copy, modify, and distribute this software for any
    8  * purpose with or without fee is hereby granted, provided that the above
    9  * copyright notice and this permission notice appear in all copies.
   10  *
   11  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   12  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   13  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   14  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   15  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   16  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   17  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   18  */
   19 
   20 /*
   21  * This is an open source non-commercial project. Dear PVS-Studio, please check it.
   22  * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
   23  */
   24 
   25 #include <config.h>
   26 
   27 #include <stdio.h>
   28 #include <stdlib.h>
   29 #include <string.h>
   30 #include <errno.h>
   31 
   32 #include "sudoers.h"
   33 #include <gram.h>
   34 
   35 struct alias_warned {
   36     SLIST_ENTRY(alias_warned) entries;
   37     const char *name;
   38 };
   39 SLIST_HEAD(alias_warned_list, alias_warned);
   40 
   41 static bool alias_warnx(const char *file, int line, int column, bool strict, bool quiet, const char *fmt, ...) __printflike(6, 7);
   42 
   43 static bool
   44 alias_warned(struct alias_warned_list *warned, char *name)
   45 {
   46     struct alias_warned *w;
   47     debug_decl(alias_warned, SUDOERS_DEBUG_ALIAS);
   48 
   49     SLIST_FOREACH(w, warned, entries) {
   50     if (strcmp(w->name, name) == 0)
   51         debug_return_bool(true);
   52     }
   53 
   54     debug_return_bool(false);
   55 }
   56 
   57 static void
   58 alias_warned_add(struct alias_warned_list *warned, char *name)
   59 {
   60     struct alias_warned *w;
   61     debug_decl(alias_warned_add, SUDOERS_DEBUG_ALIAS);
   62 
   63     w = malloc(sizeof(*w));
   64     if (w != NULL) {
   65     w->name = name;
   66     SLIST_INSERT_HEAD(warned, w, entries);
   67     }
   68 
   69     debug_return;
   70 }
   71 
   72 static bool
   73 alias_warnx(const char *file, int line, int column, bool strict, bool quiet,
   74     const char *fmt, ...)
   75 {
   76     bool ret = true;
   77     va_list ap;
   78     debug_decl(alias_warnx, SUDOERS_DEBUG_ALIAS);
   79 
   80     if (strict && sudoers_error_hook != NULL) {
   81     va_start(ap, fmt);
   82     ret = sudoers_error_hook(file, line, column, fmt, ap);
   83     va_end(ap);
   84     }
   85 
   86     if (!quiet) {
   87     int oldlocale;
   88     char *errstr;
   89 
   90     sudoers_setlocale(SUDOERS_LOCALE_USER, &oldlocale);
   91     va_start(ap, fmt);
   92     if (vasprintf(&errstr, _(fmt), ap) == -1) {
   93         errstr = NULL;
   94         ret = false;
   95     } else if (line > 0) {
   96         sudo_printf(SUDO_CONV_ERROR_MSG, _("%s:%d:%d: %s\n"), file,
   97         line, column, errstr);
   98     } else {
   99         sudo_printf(SUDO_CONV_ERROR_MSG, _("%s: %s\n"), file, errstr);
  100     }
  101     va_end(ap);
  102     sudoers_setlocale(oldlocale, NULL);
  103 
  104     free(errstr);
  105     }
  106 
  107     debug_return_bool(ret);
  108 }
  109 
  110 static int
  111 check_alias(struct sudoers_parse_tree *parse_tree,
  112     struct alias_warned_list *warned, char *name, int type,
  113     char *file, int line, int column, bool strict, bool quiet)
  114 {
  115     struct member *m;
  116     struct alias *a;
  117     int errors = 0;
  118     debug_decl(check_alias, SUDOERS_DEBUG_ALIAS);
  119 
  120     if ((a = alias_get(parse_tree, name, type)) != NULL) {
  121     /* check alias contents */
  122     TAILQ_FOREACH(m, &a->members, entries) {
  123         if (m->type != ALIAS)
  124         continue;
  125         errors += check_alias(parse_tree, warned, m->name, type,
  126         a->file, a->line, a->column, strict, quiet);
  127     }
  128     alias_put(a);
  129     } else {
  130     if (!alias_warned(warned, name)) {
  131         if (errno == ELOOP) {
  132         alias_warnx(file, line, column, strict, quiet,
  133             N_("cycle in %s \"%s\""), alias_type_to_string(type), name);
  134         } else {
  135         alias_warnx(file, line, column, strict, quiet,
  136             N_("%s \"%s\" referenced but not defined"),
  137             alias_type_to_string(type), name);
  138         }
  139         alias_warned_add(warned, name);
  140     }
  141     errors++;
  142     }
  143 
  144     debug_return_int(errors);
  145 }
  146 
  147 /*
  148  * Iterate through the sudoers datastructures looking for undefined
  149  * aliases or unused aliases.
  150  * In strict mode, returns the number of errors, else 0.
  151  */
  152 int
  153 check_aliases(struct sudoers_parse_tree *parse_tree, bool strict, bool quiet,
  154     int (*cb_unused)(struct sudoers_parse_tree *, struct alias *, void *))
  155 {
  156     struct alias_warned_list warned = SLIST_HEAD_INITIALIZER(warned);
  157     struct rbtree *used_aliases;
  158     struct alias_warned *w;
  159     struct cmndspec *cs;
  160     struct member *m;
  161     struct privilege *priv;
  162     struct userspec *us;
  163     int errors = 0;
  164     debug_decl(check_aliases, SUDOERS_DEBUG_ALIAS);
  165 
  166     used_aliases = alloc_aliases();
  167     if (used_aliases == NULL) {
  168     sudo_warnx(U_("%s: %s"), __func__, U_("unable to allocate memory"));
  169     debug_return_int(-1);
  170     }
  171 
  172     /* Forward check. */
  173     TAILQ_FOREACH(us, &parse_tree->userspecs, entries) {
  174     TAILQ_FOREACH(m, &us->users, entries) {
  175         if (m->type == ALIAS) {
  176         errors += check_alias(parse_tree, &warned, m->name, USERALIAS,
  177             us->file, us->line, us->column, strict, quiet);
  178         }
  179     }
  180     TAILQ_FOREACH(priv, &us->privileges, entries) {
  181         TAILQ_FOREACH(m, &priv->hostlist, entries) {
  182         if (m->type == ALIAS) {
  183             errors += check_alias(parse_tree, &warned, m->name, HOSTALIAS,
  184             us->file, us->line, us->column, strict, quiet);
  185         }
  186         }
  187         TAILQ_FOREACH(cs, &priv->cmndlist, entries) {
  188         if (cs->runasuserlist != NULL) {
  189             TAILQ_FOREACH(m, cs->runasuserlist, entries) {
  190             if (m->type == ALIAS) {
  191                 errors += check_alias(parse_tree, &warned, m->name, RUNASALIAS,
  192                 us->file, us->line, us->column, strict, quiet);
  193             }
  194             }
  195         }
  196         if (cs->runasgrouplist != NULL) {
  197             TAILQ_FOREACH(m, cs->runasgrouplist, entries) {
  198             if (m->type == ALIAS) {
  199                 errors += check_alias(parse_tree, &warned, m->name, RUNASALIAS,
  200                 us->file, us->line, us->column, strict, quiet);
  201             }
  202             }
  203         }
  204         if ((m = cs->cmnd)->type == ALIAS) {
  205             errors += check_alias(parse_tree, &warned, m->name, CMNDALIAS,
  206             us->file, us->line, us->column, strict, quiet);
  207         }
  208         }
  209     }
  210     }
  211     while ((w = SLIST_FIRST(&warned)) != NULL) {
  212     SLIST_REMOVE_HEAD(&warned, entries);
  213     free(w);
  214     }
  215 
  216     /* Reverse check (destructive) */
  217     if (!alias_find_used(parse_tree, used_aliases))
  218     errors++;
  219     free_aliases(used_aliases);
  220 
  221     /* If all aliases were referenced we will have an empty tree. */
  222     if (!no_aliases(parse_tree))
  223     alias_apply(parse_tree, cb_unused, &quiet);
  224 
  225     debug_return_int(strict ? errors : 0);
  226 }