--- /dev/null
+#ifndef lint
+/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
+static char yyrcsid[]
+#if __GNUC__ >= 2
+ __attribute__ ((unused))
+#endif /* __GNUC__ >= 2 */
+ = "$OpenBSD: skeleton.c,v 1.23 2004/03/12 13:39:50 henning Exp $";
+#endif
+#include <stdlib.h>
+#define YYBYACC 1
+#define YYMAJOR 1
+#define YYMINOR 9
+#define YYLEX yylex()
+#define YYEMPTY -1
+#define yyclearin (yychar=(YYEMPTY))
+#define yyerrok (yyerrflag=0)
+#define YYRECOVERING() (yyerrflag!=0)
+#define YYPREFIX "yy"
+#line 2 "gram.y"
+/*
+ * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <pwd.h>
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
+# include <alloca.h>
+#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
+
+#include "sudo.h"
+#include "parse.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+/*
+ * Globals
+ */
+extern int sudolineno;
+extern char *sudoers;
+int parse_error;
+int pedantic = FALSE;
+int verbose = FALSE;
+int errorlineno = -1;
+char *errorfile = NULL;
+
+struct alias *aliases; /* XXX - use RB or binary search tree */
+struct defaults *defaults;
+struct userspec *userspecs;
+
+/*
+ * Local protoypes
+ */
+static void add_alias __P((struct alias *));
+static void add_defaults __P((int, struct member *, struct defaults *));
+static void add_userspec __P((struct member *, struct privilege *));
+ void yyerror __P((const char *));
+
+void
+yyerror(s)
+ const char *s;
+{
+ /* Save the line the first error occurred on. */
+ if (errorlineno == -1) {
+ errorlineno = sudolineno ? sudolineno - 1 : 0;
+ errorfile = estrdup(sudoers);
+ }
+ if (verbose && s != NULL) {
+#ifndef TRACELEXER
+ (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s,
+ sudolineno ? sudolineno - 1 : 0);
+#else
+ (void) fprintf(stderr, "<*> ");
+#endif
+ }
+ parse_error = TRUE;
+}
+#line 106 "gram.y"
+#ifndef YYSTYPE_DEFINED
+#define YYSTYPE_DEFINED
+typedef union {
+ struct alias *alias;
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct privilege *privilege;
+ struct sudo_command command;
+ struct cmndtag tag;
+ char *string;
+ int tok;
+} YYSTYPE;
+#endif /* YYSTYPE_DEFINED */
+#line 138 "gram.c"
+#define COMMAND 257
+#define ALIAS 258
+#define DEFVAR 259
+#define NTWKADDR 260
+#define NETGROUP 261
+#define USERGROUP 262
+#define WORD 263
+#define DEFAULTS 264
+#define DEFAULTS_HOST 265
+#define DEFAULTS_USER 266
+#define DEFAULTS_RUNAS 267
+#define RUNAS 268
+#define NOPASSWD 269
+#define PASSWD 270
+#define NOEXEC 271
+#define EXEC 272
+#define MONITOR 273
+#define NOMONITOR 274
+#define ALL 275
+#define COMMENT 276
+#define HOSTALIAS 277
+#define CMNDALIAS 278
+#define USERALIAS 279
+#define RUNASALIAS 280
+#define ERROR 281
+#define YYERRCODE 256
+#if defined(__cplusplus) || defined(__STDC__)
+const short yylhs[] =
+#else
+short yylhs[] =
+#endif
+ { -1,
+ 0, 0, 29, 29, 30, 30, 30, 30, 30, 30,
+ 30, 30, 30, 30, 30, 12, 12, 11, 11, 11,
+ 11, 11, 27, 27, 26, 18, 18, 16, 16, 16,
+ 16, 16, 10, 10, 9, 14, 14, 22, 22, 21,
+ 21, 19, 19, 23, 23, 23, 23, 23, 28, 28,
+ 28, 28, 28, 28, 28, 13, 13, 13, 4, 4,
+ 3, 17, 17, 2, 2, 1, 15, 15, 6, 6,
+ 5, 8, 8, 7, 25, 25, 20, 20, 24, 24,
+ 24, 24, 24,
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yylen[] =
+#else
+short yylen[] =
+#endif
+ { 2,
+ 0, 1, 1, 2, 1, 2, 2, 2, 2, 2,
+ 2, 2, 3, 3, 3, 1, 3, 1, 2, 3,
+ 3, 3, 1, 3, 3, 1, 2, 1, 1, 1,
+ 1, 1, 1, 3, 3, 1, 2, 0, 2, 1,
+ 3, 1, 2, 1, 1, 1, 1, 1, 0, 2,
+ 2, 2, 2, 2, 2, 1, 1, 1, 1, 3,
+ 3, 1, 3, 1, 3, 3, 1, 3, 1, 3,
+ 3, 1, 3, 3, 1, 3, 1, 2, 1, 1,
+ 1, 1, 1,
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yydefred[] =
+#else
+short yydefred[] =
+#endif
+ { 0,
+ 0, 79, 81, 82, 83, 0, 0, 0, 0, 80,
+ 5, 0, 0, 0, 0, 0, 0, 75, 77, 0,
+ 0, 3, 6, 0, 0, 16, 0, 28, 31, 30,
+ 32, 29, 0, 26, 0, 62, 0, 44, 46, 47,
+ 48, 45, 0, 40, 0, 42, 0, 59, 0, 0,
+ 64, 0, 0, 72, 0, 0, 69, 0, 78, 0,
+ 0, 23, 0, 4, 0, 0, 0, 19, 0, 27,
+ 0, 0, 0, 43, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 76, 0, 0, 20, 21, 22,
+ 17, 63, 41, 0, 60, 58, 57, 56, 0, 36,
+ 67, 0, 65, 0, 73, 0, 70, 0, 33, 0,
+ 49, 24, 37, 0, 0, 0, 0, 68, 34, 50,
+ 51, 52, 53, 54, 55, 35,
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yydgoto[] =
+#else
+short yydgoto[] =
+#endif
+ { 17,
+ 51, 52, 48, 49, 57, 58, 54, 55, 109, 110,
+ 26, 27, 100, 101, 102, 34, 61, 36, 44, 18,
+ 45, 111, 46, 19, 20, 62, 63, 117, 21, 22,
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yysindex[] =
+#else
+short yysindex[] =
+#endif
+ { -33,
+ -270, 0, 0, 0, 0, 11, 88, 114, 140, 0,
+ 0, -237, -234, -231, -226, -244, 0, 0, 0, 62,
+ -33, 0, 0, -38, -224, 0, -8, 0, 0, 0,
+ 0, 0, -221, 0, -24, 0, -11, 0, 0, 0,
+ 0, 0, -215, 0, -3, 0, -23, 0, -9, -5,
+ 0, -1, 2, 0, 4, 3, 0, 7, 0, 114,
+ -36, 0, 8, 0, -213, -208, -205, 0, 11, 0,
+ 88, -8, -8, 0, 140, -8, 88, -237, -17, -234,
+ 114, -231, 140, -226, 0, -201, 88, 0, 0, 0,
+ 0, 0, 0, 24, 0, 0, 0, 0, -247, 0,
+ 0, 25, 0, 27, 0, 28, 0, 140, 0, 30,
+ 0, 0, 0, -17, 28, -201, -20, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yyrindex[] =
+#else
+short yyrindex[] =
+#endif
+ { 70,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 76, 0, 0, 1, 0, 0, 156, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 181, 0,
+ 0, 206, 0, 0, 236, 0, 0, 261, 0, 0,
+ 0, 0, 300, 0, 0, 0, 0, 0, 0, 0,
+ 0, 326, 352, 0, 0, 378, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 274, 0, 0, 0, 0,
+ 0, 0, 0, 26, 0, 0, 0, 0, 0, 0,
+ 0, 52, 0, 78, 0, 104, 0, 0, 0, 130,
+ 0, 0, 0, 0, 391, 274, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0,};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yygindex[] =
+#else
+short yygindex[] =
+#endif
+ { 0,
+ 6, 0, 5, 0, -7, 0, -2, 0, -37, 0,
+ 12, 16, -12, -102, 0, 49, -4, 17, 14, 31,
+ -79, 0, 47, 77, -6, 9, 0, 0, 0, 71,
+};
+#define YYTABLESIZE 666
+#if defined(__cplusplus) || defined(__STDC__)
+const short yytable[] =
+#else
+short yytable[] =
+#endif
+ { 16,
+ 18, 37, 35, 106, 66, 23, 67, 71, 25, 96,
+ 97, 118, 99, 2, 126, 99, 3, 4, 5, 71,
+ 47, 25, 65, 50, 86, 61, 53, 98, 115, 25,
+ 10, 56, 60, 18, 68, 69, 28, 77, 29, 30,
+ 75, 31, 38, 25, 18, 39, 40, 41, 78, 88,
+ 72, 66, 73, 32, 89, 79, 80, 90, 61, 42,
+ 76, 82, 81, 83, 84, 87, 108, 71, 114, 1,
+ 60, 75, 94, 116, 104, 2, 107, 74, 119, 105,
+ 91, 70, 95, 61, 66, 103, 113, 92, 93, 74,
+ 85, 64, 59, 0, 33, 112, 0, 0, 0, 0,
+ 0, 0, 0, 71, 0, 60, 0, 0, 0, 66,
+ 74, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 33, 0, 0, 0, 0, 0, 0, 0, 0, 25,
+ 0, 0, 0, 0, 0, 74, 71, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 16, 0, 0, 0,
+ 0, 0, 0, 0, 0, 12, 0, 0, 0, 0,
+ 0, 71, 25, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 43, 0, 0, 0, 0, 0, 0, 0,
+ 9, 0, 0, 0, 0, 0, 0, 25, 12, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 10, 0, 0, 0, 0,
+ 0, 0, 0, 9, 0, 0, 0, 0, 0, 0,
+ 0, 0, 1, 0, 2, 0, 0, 3, 4, 5,
+ 6, 7, 8, 9, 24, 8, 96, 97, 10, 96,
+ 97, 10, 11, 12, 13, 14, 15, 24, 120, 121,
+ 122, 123, 124, 125, 98, 24, 18, 98, 18, 0,
+ 11, 18, 18, 18, 18, 18, 18, 18, 8, 24,
+ 0, 0, 0, 0, 0, 18, 18, 18, 18, 18,
+ 18, 61, 0, 61, 0, 0, 61, 61, 61, 61,
+ 61, 61, 61, 11, 0, 0, 0, 0, 0, 7,
+ 61, 61, 61, 61, 61, 61, 38, 66, 0, 66,
+ 0, 0, 66, 66, 66, 66, 66, 66, 66, 28,
+ 0, 29, 30, 0, 31, 15, 66, 66, 66, 66,
+ 66, 66, 7, 74, 0, 74, 32, 0, 74, 74,
+ 74, 74, 74, 74, 74, 28, 0, 29, 30, 0,
+ 31, 13, 74, 74, 74, 74, 74, 74, 15, 71,
+ 0, 71, 32, 0, 71, 71, 71, 71, 71, 71,
+ 71, 2, 0, 0, 3, 4, 5, 14, 71, 71,
+ 71, 71, 71, 71, 13, 25, 0, 25, 10, 0,
+ 25, 25, 25, 25, 25, 25, 25, 38, 0, 0,
+ 39, 40, 41, 0, 25, 25, 25, 25, 25, 25,
+ 14, 12, 0, 12, 42, 0, 12, 12, 12, 12,
+ 12, 12, 12, 39, 0, 0, 0, 0, 0, 0,
+ 12, 12, 12, 12, 12, 12, 9, 0, 9, 0,
+ 0, 9, 9, 9, 9, 9, 9, 9, 0, 0,
+ 0, 0, 0, 0, 0, 9, 9, 9, 9, 9,
+ 9, 10, 0, 10, 0, 0, 10, 10, 10, 10,
+ 10, 10, 10, 0, 0, 0, 0, 0, 0, 0,
+ 10, 10, 10, 10, 10, 10, 0, 0, 0, 0,
+ 0, 8, 0, 8, 0, 0, 8, 8, 8, 8,
+ 8, 8, 8, 0, 0, 0, 0, 0, 0, 0,
+ 8, 8, 8, 8, 8, 8, 11, 0, 11, 0,
+ 0, 11, 11, 11, 11, 11, 11, 11, 0, 0,
+ 38, 38, 0, 0, 0, 11, 11, 11, 11, 11,
+ 11, 0, 38, 38, 38, 38, 38, 38, 38, 0,
+ 0, 0, 0, 0, 0, 7, 0, 7, 0, 0,
+ 7, 7, 7, 7, 7, 7, 7, 0, 0, 0,
+ 0, 0, 0, 0, 7, 7, 7, 7, 7, 7,
+ 0, 15, 0, 15, 0, 0, 15, 15, 15, 15,
+ 15, 15, 15, 0, 0, 0, 0, 0, 0, 0,
+ 15, 15, 15, 15, 15, 15, 0, 13, 0, 13,
+ 0, 0, 13, 13, 13, 13, 13, 13, 13, 0,
+ 0, 0, 0, 0, 0, 0, 13, 13, 13, 13,
+ 13, 13, 0, 14, 0, 14, 0, 0, 14, 14,
+ 14, 14, 14, 14, 14, 0, 0, 39, 39, 0,
+ 0, 0, 14, 14, 14, 14, 14, 14, 0, 39,
+ 39, 39, 39, 39, 39, 39,
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const short yycheck[] =
+#else
+short yycheck[] =
+#endif
+ { 33,
+ 0, 8, 7, 83, 43, 276, 45, 44, 33, 257,
+ 258, 114, 33, 258, 117, 33, 261, 262, 263, 44,
+ 258, 33, 61, 258, 61, 0, 258, 275, 108, 33,
+ 275, 258, 44, 33, 259, 44, 258, 61, 260, 261,
+ 44, 263, 258, 33, 44, 261, 262, 263, 58, 263,
+ 35, 0, 37, 275, 263, 61, 58, 263, 33, 275,
+ 45, 58, 61, 61, 58, 58, 268, 44, 44, 0,
+ 44, 44, 77, 44, 81, 0, 84, 0, 116, 82,
+ 69, 33, 78, 58, 33, 80, 99, 71, 75, 43,
+ 60, 21, 16, -1, 33, 87, -1, -1, -1, -1,
+ -1, -1, -1, 0, -1, 44, -1, -1, -1, 58,
+ 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ 33, -1, -1, -1, -1, -1, -1, -1, -1, 0,
+ -1, -1, -1, -1, -1, 58, 33, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, 33, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
+ -1, 58, 33, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, 33, -1, -1, -1, -1, -1, -1, -1,
+ 0, -1, -1, -1, -1, -1, -1, 58, 33, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
+ -1, -1, -1, 33, -1, -1, -1, -1, -1, -1,
+ -1, -1, 256, -1, 258, -1, -1, 261, 262, 263,
+ 264, 265, 266, 267, 259, 0, 257, 258, 33, 257,
+ 258, 275, 276, 277, 278, 279, 280, 259, 269, 270,
+ 271, 272, 273, 274, 275, 259, 256, 275, 258, -1,
+ 0, 261, 262, 263, 264, 265, 266, 267, 33, 259,
+ -1, -1, -1, -1, -1, 275, 276, 277, 278, 279,
+ 280, 256, -1, 258, -1, -1, 261, 262, 263, 264,
+ 265, 266, 267, 33, -1, -1, -1, -1, -1, 0,
+ 275, 276, 277, 278, 279, 280, 33, 256, -1, 258,
+ -1, -1, 261, 262, 263, 264, 265, 266, 267, 258,
+ -1, 260, 261, -1, 263, 0, 275, 276, 277, 278,
+ 279, 280, 33, 256, -1, 258, 275, -1, 261, 262,
+ 263, 264, 265, 266, 267, 258, -1, 260, 261, -1,
+ 263, 0, 275, 276, 277, 278, 279, 280, 33, 256,
+ -1, 258, 275, -1, 261, 262, 263, 264, 265, 266,
+ 267, 258, -1, -1, 261, 262, 263, 0, 275, 276,
+ 277, 278, 279, 280, 33, 256, -1, 258, 275, -1,
+ 261, 262, 263, 264, 265, 266, 267, 258, -1, -1,
+ 261, 262, 263, -1, 275, 276, 277, 278, 279, 280,
+ 33, 256, -1, 258, 275, -1, 261, 262, 263, 264,
+ 265, 266, 267, 33, -1, -1, -1, -1, -1, -1,
+ 275, 276, 277, 278, 279, 280, 256, -1, 258, -1,
+ -1, 261, 262, 263, 264, 265, 266, 267, -1, -1,
+ -1, -1, -1, -1, -1, 275, 276, 277, 278, 279,
+ 280, 256, -1, 258, -1, -1, 261, 262, 263, 264,
+ 265, 266, 267, -1, -1, -1, -1, -1, -1, -1,
+ 275, 276, 277, 278, 279, 280, -1, -1, -1, -1,
+ -1, 256, -1, 258, -1, -1, 261, 262, 263, 264,
+ 265, 266, 267, -1, -1, -1, -1, -1, -1, -1,
+ 275, 276, 277, 278, 279, 280, 256, -1, 258, -1,
+ -1, 261, 262, 263, 264, 265, 266, 267, -1, -1,
+ 257, 258, -1, -1, -1, 275, 276, 277, 278, 279,
+ 280, -1, 269, 270, 271, 272, 273, 274, 275, -1,
+ -1, -1, -1, -1, -1, 256, -1, 258, -1, -1,
+ 261, 262, 263, 264, 265, 266, 267, -1, -1, -1,
+ -1, -1, -1, -1, 275, 276, 277, 278, 279, 280,
+ -1, 256, -1, 258, -1, -1, 261, 262, 263, 264,
+ 265, 266, 267, -1, -1, -1, -1, -1, -1, -1,
+ 275, 276, 277, 278, 279, 280, -1, 256, -1, 258,
+ -1, -1, 261, 262, 263, 264, 265, 266, 267, -1,
+ -1, -1, -1, -1, -1, -1, 275, 276, 277, 278,
+ 279, 280, -1, 256, -1, 258, -1, -1, 261, 262,
+ 263, 264, 265, 266, 267, -1, -1, 257, 258, -1,
+ -1, -1, 275, 276, 277, 278, 279, 280, -1, 269,
+ 270, 271, 272, 273, 274, 275,
+};
+#define YYFINAL 17
+#ifndef YYDEBUG
+#define YYDEBUG 0
+#endif
+#define YYMAXTOKEN 281
+#if YYDEBUG
+#if defined(__cplusplus) || defined(__STDC__)
+const char * const yyname[] =
+#else
+char *yyname[] =
+#endif
+ {
+"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+"'!'",0,0,0,0,0,0,0,0,0,"'+'","','","'-'",0,0,0,0,0,0,0,0,0,0,0,0,"':'",0,0,
+"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
+"COMMAND","ALIAS","DEFVAR","NTWKADDR","NETGROUP","USERGROUP","WORD","DEFAULTS",
+"DEFAULTS_HOST","DEFAULTS_USER","DEFAULTS_RUNAS","RUNAS","NOPASSWD","PASSWD",
+"NOEXEC","EXEC","MONITOR","NOMONITOR","ALL","COMMENT","HOSTALIAS","CMNDALIAS",
+"USERALIAS","RUNASALIAS","ERROR",
+};
+#if defined(__cplusplus) || defined(__STDC__)
+const char * const yyrule[] =
+#else
+char *yyrule[] =
+#endif
+ {"$accept : file",
+"file :",
+"file : line",
+"line : entry",
+"line : line entry",
+"entry : COMMENT",
+"entry : error COMMENT",
+"entry : userlist privileges",
+"entry : USERALIAS useraliases",
+"entry : HOSTALIAS hostaliases",
+"entry : CMNDALIAS cmndaliases",
+"entry : RUNASALIAS runasaliases",
+"entry : DEFAULTS defaults_list",
+"entry : DEFAULTS_USER userlist defaults_list",
+"entry : DEFAULTS_RUNAS runaslist defaults_list",
+"entry : DEFAULTS_HOST hostlist defaults_list",
+"defaults_list : defaults_entry",
+"defaults_list : defaults_list ',' defaults_entry",
+"defaults_entry : DEFVAR",
+"defaults_entry : '!' DEFVAR",
+"defaults_entry : DEFVAR '=' WORD",
+"defaults_entry : DEFVAR '+' WORD",
+"defaults_entry : DEFVAR '-' WORD",
+"privileges : privilege",
+"privileges : privileges ':' privilege",
+"privilege : hostlist '=' cmndspeclist",
+"ophost : host",
+"ophost : '!' host",
+"host : ALIAS",
+"host : ALL",
+"host : NETGROUP",
+"host : NTWKADDR",
+"host : WORD",
+"cmndspeclist : cmndspec",
+"cmndspeclist : cmndspeclist ',' cmndspec",
+"cmndspec : runasspec cmndtag opcmnd",
+"opcmnd : cmnd",
+"opcmnd : '!' cmnd",
+"runasspec :",
+"runasspec : RUNAS runaslist",
+"runaslist : oprunasuser",
+"runaslist : runaslist ',' oprunasuser",
+"oprunasuser : runasuser",
+"oprunasuser : '!' runasuser",
+"runasuser : ALIAS",
+"runasuser : ALL",
+"runasuser : NETGROUP",
+"runasuser : USERGROUP",
+"runasuser : WORD",
+"cmndtag :",
+"cmndtag : cmndtag NOPASSWD",
+"cmndtag : cmndtag PASSWD",
+"cmndtag : cmndtag NOEXEC",
+"cmndtag : cmndtag EXEC",
+"cmndtag : cmndtag MONITOR",
+"cmndtag : cmndtag NOMONITOR",
+"cmnd : ALL",
+"cmnd : ALIAS",
+"cmnd : COMMAND",
+"hostaliases : hostalias",
+"hostaliases : hostaliases ':' hostalias",
+"hostalias : ALIAS '=' hostlist",
+"hostlist : ophost",
+"hostlist : hostlist ',' ophost",
+"cmndaliases : cmndalias",
+"cmndaliases : cmndaliases ':' cmndalias",
+"cmndalias : ALIAS '=' cmndlist",
+"cmndlist : opcmnd",
+"cmndlist : cmndlist ',' opcmnd",
+"runasaliases : runasalias",
+"runasaliases : runasaliases ':' runasalias",
+"runasalias : ALIAS '=' runaslist",
+"useraliases : useralias",
+"useraliases : useraliases ':' useralias",
+"useralias : ALIAS '=' userlist",
+"userlist : opuser",
+"userlist : userlist ',' opuser",
+"opuser : user",
+"opuser : '!' user",
+"user : ALIAS",
+"user : ALL",
+"user : NETGROUP",
+"user : USERGROUP",
+"user : WORD",
+};
+#endif
+#ifdef YYSTACKSIZE
+#undef YYMAXDEPTH
+#define YYMAXDEPTH YYSTACKSIZE
+#else
+#ifdef YYMAXDEPTH
+#define YYSTACKSIZE YYMAXDEPTH
+#else
+#define YYSTACKSIZE 10000
+#define YYMAXDEPTH 10000
+#endif
+#endif
+#define YYINITSTACKSIZE 200
+int yydebug;
+int yynerrs;
+int yyerrflag;
+int yychar;
+short *yyssp;
+YYSTYPE *yyvsp;
+YYSTYPE yyval;
+YYSTYPE yylval;
+short *yyss;
+short *yysslim;
+YYSTYPE *yyvs;
+int yystacksize;
+#line 508 "gram.y"
+
+/*
+ * Add a list of aliases to the end of the global aliases list.
+ */
+static void
+add_alias(a)
+ struct alias *a;
+{
+ if (aliases == NULL)
+ aliases = a;
+ else {
+ if (aliases->last != NULL)
+ aliases->last->next = a;
+ else /* if (aliases->next == NULL) */
+ aliases->next = a;
+ aliases->last = a->last ? a->last : a;
+ }
+}
+
+/*
+ * Add a list of defaults structures to the defaults list.
+ * The binding, if non-NULL, specifies a list of hosts, users, or
+ * runas users the entries apply to (specified by the type).
+ */
+static void
+add_defaults(type, binding, defs)
+ int type;
+ struct member *binding;
+ struct defaults *defs;
+{
+ struct defaults *d;
+
+ /*
+ * Set type and binding (who it applies to) for new entries.
+ */
+ for (d = defs; d != NULL; d = d->next) {
+ d->type = type;
+ d->binding = binding;
+ }
+ if (defaults == NULL)
+ defaults = defs;
+ else {
+ if (defaults->last != NULL)
+ defaults->last->next = defs;
+ else /* if (defaults->next == NULL) */
+ defaults->next = defs;
+ defaults->last = defs->last ? defs->last : defs;
+ }
+}
+
+/*
+ * Allocate a new struct userspec, populate it, and insert it at the
+ * and of the userspecs list.
+ */
+static void
+add_userspec(members, privs)
+ struct member *members;
+ struct privilege *privs;
+{
+ struct userspec *u;
+
+ u = emalloc(sizeof(*u));
+ u->user = members;
+ u->privileges = privs;
+ u->last = NULL;
+ u->next = NULL;
+ if (userspecs == NULL)
+ userspecs = u;
+ else {
+ if (userspecs->last != NULL)
+ userspecs->last->next = u;
+ else /* if (userspecs->next == NULL) */
+ userspecs->next = u;
+ userspecs->last = u;
+ }
+}
+
+/*
+ * Free up space used by data structures from a previous parser run and sets
+ * the current sudoers file to path.
+ */
+void
+init_parser(path, quiet)
+ char *path;
+ int quiet;
+{
+ struct alias *a;
+ struct defaults *d;
+ struct member *m, *lastbinding;
+ struct userspec *us;
+ struct privilege *priv;
+ struct cmndspec *cs;
+ VOID *next;
+
+ for (a = aliases ; a != NULL; a = a->next) {
+ for (m = a->first_member; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ }
+ aliases = NULL;
+
+ for (us = userspecs ; us != NULL; us = next) {
+ for (m = us->user; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ for (priv = us->privileges; priv != NULL; priv = next) {
+ for (m = priv->hostlist; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ for (cs = priv->cmndlist; cs != NULL; cs = next) {
+ for (m = cs->runaslist; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ if (cs->cmnd->name != NULL)
+ free(cs->cmnd->name);
+ free(cs->cmnd);
+ next = cs->next;
+ free(cs);
+ }
+ next = priv->next;
+ free(priv);
+ }
+ next = us->next;
+ free(us);
+ }
+ userspecs = NULL;
+
+ lastbinding = NULL;
+ for (d = defaults ; d != NULL; d = next) {
+ if (d->binding != lastbinding) {
+ for (m = d->binding; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ lastbinding = d->binding;
+ }
+ next = d->next;
+ free(d->var);
+ if (d->val != NULL)
+ free(d->val);
+ free(d);
+ }
+ defaults = NULL;
+
+ if (sudoers != NULL)
+ free(sudoers);
+ sudoers = estrdup(path);
+
+ parse_error = FALSE;
+ errorlineno = -1;
+ sudolineno = 1;
+ verbose = !quiet;
+}
+#line 679 "gram.c"
+/* allocate initial stack or double stack size, up to YYMAXDEPTH */
+#if defined(__cplusplus) || defined(__STDC__)
+static int yygrowstack(void)
+#else
+static int yygrowstack()
+#endif
+{
+ int newsize, i;
+ short *newss;
+ YYSTYPE *newvs;
+
+ if ((newsize = yystacksize) == 0)
+ newsize = YYINITSTACKSIZE;
+ else if (newsize >= YYMAXDEPTH)
+ return -1;
+ else if ((newsize *= 2) > YYMAXDEPTH)
+ newsize = YYMAXDEPTH;
+ i = yyssp - yyss;
+ newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
+ (short *)malloc(newsize * sizeof *newss);
+ if (newss == NULL)
+ goto bail;
+ yyss = newss;
+ yyssp = newss + i;
+ newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
+ (YYSTYPE *)malloc(newsize * sizeof *newvs);
+ if (newvs == NULL)
+ goto bail;
+ yyvs = newvs;
+ yyvsp = newvs + i;
+ yystacksize = newsize;
+ yysslim = yyss + newsize - 1;
+ return 0;
+bail:
+ if (yyss)
+ free(yyss);
+ if (yyvs)
+ free(yyvs);
+ yyss = yyssp = NULL;
+ yyvs = yyvsp = NULL;
+ yystacksize = 0;
+ return -1;
+}
+
+#define YYABORT goto yyabort
+#define YYREJECT goto yyabort
+#define YYACCEPT goto yyaccept
+#define YYERROR goto yyerrlab
+int
+#if defined(__cplusplus) || defined(__STDC__)
+yyparse(void)
+#else
+yyparse()
+#endif
+{
+ int yym, yyn, yystate;
+#if YYDEBUG
+#if defined(__cplusplus) || defined(__STDC__)
+ const char *yys;
+#else /* !(defined(__cplusplus) || defined(__STDC__)) */
+ char *yys;
+#endif /* !(defined(__cplusplus) || defined(__STDC__)) */
+
+ if ((yys = getenv("YYDEBUG")))
+ {
+ yyn = *yys;
+ if (yyn >= '0' && yyn <= '9')
+ yydebug = yyn - '0';
+ }
+#endif /* YYDEBUG */
+
+ yynerrs = 0;
+ yyerrflag = 0;
+ yychar = (-1);
+
+ if (yyss == NULL && yygrowstack()) goto yyoverflow;
+ yyssp = yyss;
+ yyvsp = yyvs;
+ *yyssp = yystate = 0;
+
+yyloop:
+ if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ }
+ if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, shifting to state %d\n",
+ YYPREFIX, yystate, yytable[yyn]);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ yychar = (-1);
+ if (yyerrflag > 0) --yyerrflag;
+ goto yyloop;
+ }
+ if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
+ {
+ yyn = yytable[yyn];
+ goto yyreduce;
+ }
+ if (yyerrflag) goto yyinrecovery;
+#if defined(lint) || defined(__GNUC__)
+ goto yynewerror;
+#endif
+yynewerror:
+ yyerror("syntax error");
+#if defined(lint) || defined(__GNUC__)
+ goto yyerrlab;
+#endif
+yyerrlab:
+ ++yynerrs;
+yyinrecovery:
+ if (yyerrflag < 3)
+ {
+ yyerrflag = 3;
+ for (;;)
+ {
+ if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, error recovery shifting\
+ to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate = yytable[yyn];
+ *++yyvsp = yylval;
+ goto yyloop;
+ }
+ else
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: error recovery discarding state %d\n",
+ YYPREFIX, *yyssp);
+#endif
+ if (yyssp <= yyss) goto yyabort;
+ --yyssp;
+ --yyvsp;
+ }
+ }
+ }
+ else
+ {
+ if (yychar == 0) goto yyabort;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
+ YYPREFIX, yystate, yychar, yys);
+ }
+#endif
+ yychar = (-1);
+ goto yyloop;
+ }
+yyreduce:
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: state %d, reducing by rule %d (%s)\n",
+ YYPREFIX, yystate, yyn, yyrule[yyn]);
+#endif
+ yym = yylen[yyn];
+ yyval = yyvsp[1-yym];
+ switch (yyn)
+ {
+case 1:
+#line 177 "gram.y"
+{ ; }
+break;
+case 5:
+#line 185 "gram.y"
+{
+ ;
+ }
+break;
+case 6:
+#line 188 "gram.y"
+{
+ yyerrok;
+ }
+break;
+case 7:
+#line 191 "gram.y"
+{
+ add_userspec(yyvsp[-1].member, yyvsp[0].privilege);
+ }
+break;
+case 8:
+#line 194 "gram.y"
+{
+ add_alias(yyvsp[0].alias);
+ }
+break;
+case 9:
+#line 197 "gram.y"
+{
+ add_alias(yyvsp[0].alias);
+ }
+break;
+case 10:
+#line 200 "gram.y"
+{
+ add_alias(yyvsp[0].alias);
+ }
+break;
+case 11:
+#line 203 "gram.y"
+{
+ add_alias(yyvsp[0].alias);
+ }
+break;
+case 12:
+#line 206 "gram.y"
+{
+ add_defaults(DEFAULTS, NULL, yyvsp[0].defaults);
+ }
+break;
+case 13:
+#line 209 "gram.y"
+{
+ add_defaults(DEFAULTS_USER, yyvsp[-1].member, yyvsp[0].defaults);
+ }
+break;
+case 14:
+#line 212 "gram.y"
+{
+ add_defaults(DEFAULTS_RUNAS, yyvsp[-1].member, yyvsp[0].defaults);
+ }
+break;
+case 15:
+#line 215 "gram.y"
+{
+ add_defaults(DEFAULTS_HOST, yyvsp[-1].member, yyvsp[0].defaults);
+ }
+break;
+case 17:
+#line 221 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].defaults, yyvsp[0].defaults);
+ yyval.defaults = yyvsp[-2].defaults;
+ }
+break;
+case 18:
+#line 227 "gram.y"
+{
+ NEW_DEFAULT(yyval.defaults, yyvsp[0].string, NULL, TRUE);
+ }
+break;
+case 19:
+#line 230 "gram.y"
+{
+ NEW_DEFAULT(yyval.defaults, yyvsp[0].string, NULL, FALSE);
+ }
+break;
+case 20:
+#line 233 "gram.y"
+{
+ NEW_DEFAULT(yyval.defaults, yyvsp[-2].string, yyvsp[0].string, TRUE);
+ }
+break;
+case 21:
+#line 236 "gram.y"
+{
+ NEW_DEFAULT(yyval.defaults, yyvsp[-2].string, yyvsp[0].string, '+');
+ }
+break;
+case 22:
+#line 239 "gram.y"
+{
+ NEW_DEFAULT(yyval.defaults, yyvsp[-2].string, yyvsp[0].string, '-');
+ }
+break;
+case 24:
+#line 245 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].privilege, yyvsp[0].privilege);
+ yyval.privilege = yyvsp[-2].privilege;
+ }
+break;
+case 25:
+#line 251 "gram.y"
+{
+ struct cmndtag tags;
+ struct privilege *p = emalloc(sizeof(*p));
+ struct cmndspec *cs;
+ p->hostlist = yyvsp[-2].member;
+ p->cmndlist = yyvsp[0].cmndspec;
+ tags.nopasswd = tags.noexec = tags.monitor = UNSPEC;
+ /* propagate tags */
+ for (cs = yyvsp[0].cmndspec; cs != NULL; cs = cs->next) {
+ if (cs->tags.nopasswd == UNSPEC)
+ cs->tags.nopasswd = tags.nopasswd;
+ if (cs->tags.noexec == UNSPEC)
+ cs->tags.noexec = tags.noexec;
+ if (cs->tags.monitor == UNSPEC)
+ cs->tags.monitor = tags.monitor;
+ memcpy(&tags, &cs->tags, sizeof(tags));
+ }
+ p->last = NULL;
+ p->next = NULL;
+ yyval.privilege = p;
+ }
+break;
+case 26:
+#line 274 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = FALSE;
+ }
+break;
+case 27:
+#line 278 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = TRUE;
+ }
+break;
+case 28:
+#line 284 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, HOSTALIAS);
+ }
+break;
+case 29:
+#line 287 "gram.y"
+{
+ NEW_MEMBER(yyval.member, NULL, ALL);
+ }
+break;
+case 30:
+#line 290 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, NETGROUP);
+ }
+break;
+case 31:
+#line 293 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, NTWKADDR);
+ }
+break;
+case 32:
+#line 296 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, WORD);
+ }
+break;
+case 34:
+#line 302 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].cmndspec, yyvsp[0].cmndspec);
+ yyval.cmndspec = yyvsp[-2].cmndspec;
+ }
+break;
+case 35:
+#line 308 "gram.y"
+{
+ struct cmndspec *cs = emalloc(sizeof(*cs));
+ cs->runaslist = yyvsp[-2].member;
+ cs->tags = yyvsp[-1].tag;
+ cs->cmnd = yyvsp[0].member;
+ cs->last = NULL;
+ cs->next = NULL;
+ yyval.cmndspec = cs;
+ }
+break;
+case 36:
+#line 319 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = FALSE;
+ }
+break;
+case 37:
+#line 323 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = TRUE;
+ }
+break;
+case 38:
+#line 329 "gram.y"
+{
+ yyval.member = NULL;
+ }
+break;
+case 39:
+#line 332 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ }
+break;
+case 41:
+#line 338 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].member, yyvsp[0].member);
+ yyval.member = yyvsp[-2].member;
+ }
+break;
+case 42:
+#line 344 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = FALSE;
+ }
+break;
+case 43:
+#line 348 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = TRUE;
+ }
+break;
+case 44:
+#line 354 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, RUNASALIAS);
+ }
+break;
+case 45:
+#line 357 "gram.y"
+{
+ NEW_MEMBER(yyval.member, NULL, ALL);
+ }
+break;
+case 46:
+#line 360 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, NETGROUP);
+ }
+break;
+case 47:
+#line 363 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, USERGROUP);
+ }
+break;
+case 48:
+#line 366 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, WORD);
+ }
+break;
+case 49:
+#line 371 "gram.y"
+{
+ yyval.tag.nopasswd = yyval.tag.noexec = yyval.tag.monitor = UNSPEC;
+ }
+break;
+case 50:
+#line 374 "gram.y"
+{
+ yyval.tag.nopasswd = TRUE;
+ }
+break;
+case 51:
+#line 377 "gram.y"
+{
+ yyval.tag.nopasswd = FALSE;
+ }
+break;
+case 52:
+#line 380 "gram.y"
+{
+ yyval.tag.noexec = TRUE;
+ }
+break;
+case 53:
+#line 383 "gram.y"
+{
+ yyval.tag.noexec = FALSE;
+ }
+break;
+case 54:
+#line 386 "gram.y"
+{
+ yyval.tag.monitor = TRUE;
+ }
+break;
+case 55:
+#line 389 "gram.y"
+{
+ yyval.tag.monitor = FALSE;
+ }
+break;
+case 56:
+#line 394 "gram.y"
+{
+ NEW_MEMBER(yyval.member, NULL, ALL);
+ if (safe_cmnd)
+ free(safe_cmnd);
+ safe_cmnd = estrdup(user_cmnd);
+ }
+break;
+case 57:
+#line 400 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, CMNDALIAS);
+ }
+break;
+case 58:
+#line 403 "gram.y"
+{
+ struct sudo_command *c = emalloc(sizeof(*c));
+ c->cmnd = yyvsp[0].command.cmnd;
+ c->args = yyvsp[0].command.args;
+ NEW_MEMBER(yyval.member, (char *)c, COMMAND);
+ }
+break;
+case 60:
+#line 412 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].alias, yyvsp[0].alias);
+ yyval.alias = yyvsp[-2].alias;
+ }
+break;
+case 61:
+#line 418 "gram.y"
+{
+ NEW_ALIAS(yyval.alias, yyvsp[-2].string, HOSTALIAS, yyvsp[0].member);
+ }
+break;
+case 63:
+#line 424 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].member, yyvsp[0].member);
+ yyval.member = yyvsp[-2].member;
+ }
+break;
+case 65:
+#line 431 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].alias, yyvsp[0].alias);
+ yyval.alias = yyvsp[-2].alias;
+ }
+break;
+case 66:
+#line 437 "gram.y"
+{
+ NEW_ALIAS(yyval.alias, yyvsp[-2].string, CMNDALIAS, yyvsp[0].member);
+ }
+break;
+case 68:
+#line 443 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].member, yyvsp[0].member);
+ yyval.member = yyvsp[-2].member;
+ }
+break;
+case 70:
+#line 450 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].alias, yyvsp[0].alias);
+ yyval.alias = yyvsp[-2].alias;
+ }
+break;
+case 71:
+#line 456 "gram.y"
+{
+ NEW_ALIAS(yyval.alias, yyvsp[-2].string, RUNASALIAS, yyvsp[0].member);
+ }
+break;
+case 73:
+#line 462 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].alias, yyvsp[0].alias);
+ yyval.alias = yyvsp[-2].alias;
+ }
+break;
+case 74:
+#line 468 "gram.y"
+{
+ NEW_ALIAS(yyval.alias, yyvsp[-2].string, USERALIAS, yyvsp[0].member);
+ }
+break;
+case 76:
+#line 474 "gram.y"
+{
+ LIST_APPEND(yyvsp[-2].member, yyvsp[0].member);
+ yyval.member = yyvsp[-2].member;
+ }
+break;
+case 77:
+#line 480 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = FALSE;
+ }
+break;
+case 78:
+#line 484 "gram.y"
+{
+ yyval.member = yyvsp[0].member;
+ yyval.member->negated = TRUE;
+ }
+break;
+case 79:
+#line 490 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, USERALIAS);
+ }
+break;
+case 80:
+#line 493 "gram.y"
+{
+ NEW_MEMBER(yyval.member, NULL, ALL);
+ }
+break;
+case 81:
+#line 496 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, NETGROUP);
+ }
+break;
+case 82:
+#line 499 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, USERGROUP);
+ }
+break;
+case 83:
+#line 502 "gram.y"
+{
+ NEW_MEMBER(yyval.member, yyvsp[0].string, WORD);
+ }
+break;
+#line 1333 "gram.c"
+ }
+ yyssp -= yym;
+ yystate = *yyssp;
+ yyvsp -= yym;
+ yym = yylhs[yyn];
+ if (yystate == 0 && yym == 0)
+ {
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state 0 to\
+ state %d\n", YYPREFIX, YYFINAL);
+#endif
+ yystate = YYFINAL;
+ *++yyssp = YYFINAL;
+ *++yyvsp = yyval;
+ if (yychar < 0)
+ {
+ if ((yychar = yylex()) < 0) yychar = 0;
+#if YYDEBUG
+ if (yydebug)
+ {
+ yys = 0;
+ if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
+ if (!yys) yys = "illegal-symbol";
+ printf("%sdebug: state %d, reading %d (%s)\n",
+ YYPREFIX, YYFINAL, yychar, yys);
+ }
+#endif
+ }
+ if (yychar == 0) goto yyaccept;
+ goto yyloop;
+ }
+ if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
+ yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
+ yystate = yytable[yyn];
+ else
+ yystate = yydgoto[yym];
+#if YYDEBUG
+ if (yydebug)
+ printf("%sdebug: after reduction, shifting from state %d \
+to state %d\n", YYPREFIX, *yyssp, yystate);
+#endif
+ if (yyssp >= yysslim && yygrowstack())
+ {
+ goto yyoverflow;
+ }
+ *++yyssp = yystate;
+ *++yyvsp = yyval;
+ goto yyloop;
+yyoverflow:
+ yyerror("yacc stack overflow");
+yyabort:
+ if (yyss)
+ free(yyss);
+ if (yyvs)
+ free(yyvs);
+ yyss = yyssp = NULL;
+ yyvs = yyvsp = NULL;
+ yystacksize = 0;
+ return (1);
+yyaccept:
+ if (yyss)
+ free(yyss);
+ if (yyvs)
+ free(yyvs);
+ yyss = yyssp = NULL;
+ yyvs = yyvsp = NULL;
+ yystacksize = 0;
+ return (0);
+}
#ifndef YYSTYPE_DEFINED
#define YYSTYPE_DEFINED
typedef union {
- char *string;
- int BOOLEAN;
+ struct alias *alias;
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct privilege *privilege;
struct sudo_command command;
+ struct cmndtag tag;
+ char *string;
int tok;
} YYSTYPE;
#endif /* YYSTYPE_DEFINED */
--- /dev/null
+%{
+/*
+ * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include "config.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif /* STDC_HEADERS */
+#ifdef HAVE_STRING_H
+# include <string.h>
+#else
+# ifdef HAVE_STRINGS_H
+# include <strings.h>
+# endif
+#endif /* HAVE_STRING_H */
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#include <pwd.h>
+#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
+# include <malloc.h>
+#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
+#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
+# include <alloca.h>
+#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
+
+#include "sudo.h"
+#include "parse.h"
+
+#ifndef lint
+static const char rcsid[] = "$Sudo$";
+#endif /* lint */
+
+/*
+ * Globals
+ */
+extern int sudolineno;
+extern char *sudoers;
+int parse_error;
+int pedantic = FALSE;
+int verbose = FALSE;
+int errorlineno = -1;
+char *errorfile = NULL;
+
+struct alias *aliases; /* XXX - use RB or binary search tree */
+struct defaults *defaults;
+struct userspec *userspecs;
+
+/*
+ * Local protoypes
+ */
+static void add_alias __P((struct alias *));
+static void add_defaults __P((int, struct member *, struct defaults *));
+static void add_userspec __P((struct member *, struct privilege *));
+ void yyerror __P((const char *));
+
+void
+yyerror(s)
+ const char *s;
+{
+ /* Save the line the first error occurred on. */
+ if (errorlineno == -1) {
+ errorlineno = sudolineno ? sudolineno - 1 : 0;
+ errorfile = estrdup(sudoers);
+ }
+ if (verbose && s != NULL) {
+#ifndef TRACELEXER
+ (void) fprintf(stderr, ">>> %s: %s near line %d <<<\n", sudoers, s,
+ sudolineno ? sudolineno - 1 : 0);
+#else
+ (void) fprintf(stderr, "<*> ");
+#endif
+ }
+ parse_error = TRUE;
+}
+%}
+
+%union {
+ struct alias *alias;
+ struct cmndspec *cmndspec;
+ struct defaults *defaults;
+ struct member *member;
+ struct privilege *privilege;
+ struct sudo_command command;
+ struct cmndtag tag;
+ char *string;
+ int tok;
+}
+
+%start file /* special start symbol */
+%token <command> COMMAND /* absolute pathname w/ optional args */
+%token <string> ALIAS /* an UPPERCASE alias name */
+%token <string> DEFVAR /* a Defaults variable name */
+%token <string> NTWKADDR /* w.x.y.z */
+%token <string> NETGROUP /* a netgroup (+NAME) */
+%token <string> USERGROUP /* a usergroup (%NAME) */
+%token <string> WORD /* a word */
+%token <tok> DEFAULTS /* Defaults entry */
+%token <tok> DEFAULTS_HOST /* Host-specific defaults entry */
+%token <tok> DEFAULTS_USER /* User-specific defaults entry */
+%token <tok> DEFAULTS_RUNAS /* Runas-specific defaults entry */
+%token <tok> RUNAS /* ( runas_list ) */
+%token <tok> NOPASSWD /* no passwd req for command */
+%token <tok> PASSWD /* passwd req for command (default) */
+%token <tok> NOEXEC /* preload dummy execve() for cmnd */
+%token <tok> EXEC /* don't preload dummy execve() */
+%token <tok> MONITOR /* monitor children of cmnd */
+%token <tok> NOMONITOR /* disable monitoring of children */
+%token <tok> ALL /* ALL keyword */
+%token <tok> COMMENT /* comment and/or carriage return */
+%token <tok> HOSTALIAS /* Host_Alias keyword */
+%token <tok> CMNDALIAS /* Cmnd_Alias keyword */
+%token <tok> USERALIAS /* User_Alias keyword */
+%token <tok> RUNASALIAS /* Runas_Alias keyword */
+%token <tok> ':' '=' ',' '!' '+' '-' /* union member tokens */
+%token <tok> ERROR
+
+%type <alias> cmndalias
+%type <alias> cmndaliases
+%type <alias> hostalias
+%type <alias> hostaliases
+%type <alias> runasalias
+%type <alias> runasaliases
+%type <alias> useralias
+%type <alias> useraliases
+%type <cmndspec> cmndspec
+%type <cmndspec> cmndspeclist
+%type <defaults> defaults_entry
+%type <defaults> defaults_list
+%type <member> cmnd
+%type <member> opcmnd
+%type <member> cmndlist
+%type <member> host
+%type <member> hostlist
+%type <member> ophost
+%type <member> oprunasuser
+%type <member> opuser
+%type <member> runaslist
+%type <member> runasspec
+%type <member> runasuser
+%type <member> user
+%type <member> userlist
+%type <privilege> privilege
+%type <privilege> privileges
+%type <tag> cmndtag
+
+%%
+
+file : { ; }
+ | line
+ ;
+
+line : entry
+ | line entry
+ ;
+
+entry : COMMENT {
+ ;
+ }
+ | error COMMENT {
+ yyerrok;
+ }
+ | userlist privileges {
+ add_userspec($1, $2);
+ }
+ | USERALIAS useraliases {
+ add_alias($2);
+ }
+ | HOSTALIAS hostaliases {
+ add_alias($2);
+ }
+ | CMNDALIAS cmndaliases {
+ add_alias($2);
+ }
+ | RUNASALIAS runasaliases {
+ add_alias($2);
+ }
+ | DEFAULTS defaults_list {
+ add_defaults(DEFAULTS, NULL, $2);
+ }
+ | DEFAULTS_USER userlist defaults_list {
+ add_defaults(DEFAULTS_USER, $2, $3);
+ }
+ | DEFAULTS_RUNAS runaslist defaults_list {
+ add_defaults(DEFAULTS_RUNAS, $2, $3);
+ }
+ | DEFAULTS_HOST hostlist defaults_list {
+ add_defaults(DEFAULTS_HOST, $2, $3);
+ }
+ ;
+
+defaults_list : defaults_entry
+ | defaults_list ',' defaults_entry {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+defaults_entry : DEFVAR {
+ NEW_DEFAULT($$, $1, NULL, TRUE);
+ }
+ | '!' DEFVAR {
+ NEW_DEFAULT($$, $2, NULL, FALSE);
+ }
+ | DEFVAR '=' WORD {
+ NEW_DEFAULT($$, $1, $3, TRUE);
+ }
+ | DEFVAR '+' WORD {
+ NEW_DEFAULT($$, $1, $3, '+');
+ }
+ | DEFVAR '-' WORD {
+ NEW_DEFAULT($$, $1, $3, '-');
+ }
+ ;
+
+privileges : privilege
+ | privileges ':' privilege {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+privilege : hostlist '=' cmndspeclist {
+ struct cmndtag tags;
+ struct privilege *p = emalloc(sizeof(*p));
+ struct cmndspec *cs;
+ p->hostlist = $1;
+ p->cmndlist = $3;
+ tags.nopasswd = tags.noexec = tags.monitor = UNSPEC;
+ /* propagate tags */
+ for (cs = $3; cs != NULL; cs = cs->next) {
+ if (cs->tags.nopasswd == UNSPEC)
+ cs->tags.nopasswd = tags.nopasswd;
+ if (cs->tags.noexec == UNSPEC)
+ cs->tags.noexec = tags.noexec;
+ if (cs->tags.monitor == UNSPEC)
+ cs->tags.monitor = tags.monitor;
+ memcpy(&tags, &cs->tags, sizeof(tags));
+ }
+ p->last = NULL;
+ p->next = NULL;
+ $$ = p;
+ }
+ ;
+
+ophost : host {
+ $$ = $1;
+ $$->negated = FALSE;
+ }
+ | '!' host {
+ $$ = $2;
+ $$->negated = TRUE;
+ }
+ ;
+
+host : ALIAS {
+ NEW_MEMBER($$, $1, HOSTALIAS);
+ }
+ | ALL {
+ NEW_MEMBER($$, NULL, ALL);
+ }
+ | NETGROUP {
+ NEW_MEMBER($$, $1, NETGROUP);
+ }
+ | NTWKADDR {
+ NEW_MEMBER($$, $1, NTWKADDR);
+ }
+ | WORD {
+ NEW_MEMBER($$, $1, WORD);
+ }
+ ;
+
+cmndspeclist : cmndspec
+ | cmndspeclist ',' cmndspec {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+cmndspec : runasspec cmndtag opcmnd {
+ struct cmndspec *cs = emalloc(sizeof(*cs));
+ cs->runaslist = $1;
+ cs->tags = $2;
+ cs->cmnd = $3;
+ cs->last = NULL;
+ cs->next = NULL;
+ $$ = cs;
+ }
+ ;
+
+opcmnd : cmnd {
+ $$ = $1;
+ $$->negated = FALSE;
+ }
+ | '!' cmnd {
+ $$ = $2;
+ $$->negated = TRUE;
+ }
+ ;
+
+runasspec : /* empty */ {
+ $$ = NULL;
+ }
+ | RUNAS runaslist {
+ $$ = $2;
+ }
+ ;
+
+runaslist : oprunasuser
+ | runaslist ',' oprunasuser {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+oprunasuser : runasuser {
+ $$ = $1;
+ $$->negated = FALSE;
+ }
+ | '!' runasuser {
+ $$ = $2;
+ $$->negated = TRUE;
+ }
+ ;
+
+runasuser : ALIAS {
+ NEW_MEMBER($$, $1, RUNASALIAS);
+ }
+ | ALL {
+ NEW_MEMBER($$, NULL, ALL);
+ }
+ | NETGROUP {
+ NEW_MEMBER($$, $1, NETGROUP);
+ }
+ | USERGROUP {
+ NEW_MEMBER($$, $1, USERGROUP);
+ }
+ | WORD {
+ NEW_MEMBER($$, $1, WORD);
+ }
+ ;
+
+cmndtag : /* empty */ {
+ $$.nopasswd = $$.noexec = $$.monitor = UNSPEC;
+ }
+ | cmndtag NOPASSWD {
+ $$.nopasswd = TRUE;
+ }
+ | cmndtag PASSWD {
+ $$.nopasswd = FALSE;
+ }
+ | cmndtag NOEXEC {
+ $$.noexec = TRUE;
+ }
+ | cmndtag EXEC {
+ $$.noexec = FALSE;
+ }
+ | cmndtag MONITOR {
+ $$.monitor = TRUE;
+ }
+ | cmndtag NOMONITOR {
+ $$.monitor = FALSE;
+ }
+ ;
+
+cmnd : ALL {
+ NEW_MEMBER($$, NULL, ALL);
+ if (safe_cmnd)
+ free(safe_cmnd);
+ safe_cmnd = estrdup(user_cmnd);
+ }
+ | ALIAS {
+ NEW_MEMBER($$, $1, CMNDALIAS);
+ }
+ | COMMAND {
+ struct sudo_command *c = emalloc(sizeof(*c));
+ c->cmnd = $1.cmnd;
+ c->args = $1.args;
+ NEW_MEMBER($$, (char *)c, COMMAND);
+ }
+ ;
+
+hostaliases : hostalias
+ | hostaliases ':' hostalias {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+hostalias : ALIAS '=' hostlist {
+ NEW_ALIAS($$, $1, HOSTALIAS, $3);
+ }
+ ;
+
+hostlist : ophost
+ | hostlist ',' ophost {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+cmndaliases : cmndalias
+ | cmndaliases ':' cmndalias {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+cmndalias : ALIAS '=' cmndlist {
+ NEW_ALIAS($$, $1, CMNDALIAS, $3);
+ }
+ ;
+
+cmndlist : opcmnd
+ | cmndlist ',' opcmnd {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+runasaliases : runasalias
+ | runasaliases ':' runasalias {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+runasalias : ALIAS '=' runaslist {
+ NEW_ALIAS($$, $1, RUNASALIAS, $3);
+ }
+ ;
+
+useraliases : useralias
+ | useraliases ':' useralias {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+useralias : ALIAS '=' userlist {
+ NEW_ALIAS($$, $1, USERALIAS, $3);
+ }
+ ;
+
+userlist : opuser
+ | userlist ',' opuser {
+ LIST_APPEND($1, $3);
+ $$ = $1;
+ }
+ ;
+
+opuser : user {
+ $$ = $1;
+ $$->negated = FALSE;
+ }
+ | '!' user {
+ $$ = $2;
+ $$->negated = TRUE;
+ }
+ ;
+
+user : ALIAS {
+ NEW_MEMBER($$, $1, USERALIAS);
+ }
+ | ALL {
+ NEW_MEMBER($$, NULL, ALL);
+ }
+ | NETGROUP {
+ NEW_MEMBER($$, $1, NETGROUP);
+ }
+ | USERGROUP {
+ NEW_MEMBER($$, $1, USERGROUP);
+ }
+ | WORD {
+ NEW_MEMBER($$, $1, WORD);
+ }
+ ;
+
+%%
+
+/*
+ * Add a list of aliases to the end of the global aliases list.
+ */
+static void
+add_alias(a)
+ struct alias *a;
+{
+ if (aliases == NULL)
+ aliases = a;
+ else {
+ if (aliases->last != NULL)
+ aliases->last->next = a;
+ else /* if (aliases->next == NULL) */
+ aliases->next = a;
+ aliases->last = a->last ? a->last : a;
+ }
+}
+
+/*
+ * Add a list of defaults structures to the defaults list.
+ * The binding, if non-NULL, specifies a list of hosts, users, or
+ * runas users the entries apply to (specified by the type).
+ */
+static void
+add_defaults(type, binding, defs)
+ int type;
+ struct member *binding;
+ struct defaults *defs;
+{
+ struct defaults *d;
+
+ /*
+ * Set type and binding (who it applies to) for new entries.
+ */
+ for (d = defs; d != NULL; d = d->next) {
+ d->type = type;
+ d->binding = binding;
+ }
+ if (defaults == NULL)
+ defaults = defs;
+ else {
+ if (defaults->last != NULL)
+ defaults->last->next = defs;
+ else /* if (defaults->next == NULL) */
+ defaults->next = defs;
+ defaults->last = defs->last ? defs->last : defs;
+ }
+}
+
+/*
+ * Allocate a new struct userspec, populate it, and insert it at the
+ * and of the userspecs list.
+ */
+static void
+add_userspec(members, privs)
+ struct member *members;
+ struct privilege *privs;
+{
+ struct userspec *u;
+
+ u = emalloc(sizeof(*u));
+ u->user = members;
+ u->privileges = privs;
+ u->last = NULL;
+ u->next = NULL;
+ if (userspecs == NULL)
+ userspecs = u;
+ else {
+ if (userspecs->last != NULL)
+ userspecs->last->next = u;
+ else /* if (userspecs->next == NULL) */
+ userspecs->next = u;
+ userspecs->last = u;
+ }
+}
+
+/*
+ * Free up space used by data structures from a previous parser run and sets
+ * the current sudoers file to path.
+ */
+void
+init_parser(path, quiet)
+ char *path;
+ int quiet;
+{
+ struct alias *a;
+ struct defaults *d;
+ struct member *m, *lastbinding;
+ struct userspec *us;
+ struct privilege *priv;
+ struct cmndspec *cs;
+ VOID *next;
+
+ for (a = aliases ; a != NULL; a = a->next) {
+ for (m = a->first_member; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ }
+ aliases = NULL;
+
+ for (us = userspecs ; us != NULL; us = next) {
+ for (m = us->user; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ for (priv = us->privileges; priv != NULL; priv = next) {
+ for (m = priv->hostlist; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ for (cs = priv->cmndlist; cs != NULL; cs = next) {
+ for (m = cs->runaslist; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ if (cs->cmnd->name != NULL)
+ free(cs->cmnd->name);
+ free(cs->cmnd);
+ next = cs->next;
+ free(cs);
+ }
+ next = priv->next;
+ free(priv);
+ }
+ next = us->next;
+ free(us);
+ }
+ userspecs = NULL;
+
+ lastbinding = NULL;
+ for (d = defaults ; d != NULL; d = next) {
+ if (d->binding != lastbinding) {
+ for (m = d->binding; m != NULL; m = next) {
+ next = m->next;
+ if (m->name != NULL)
+ free(m->name);
+ free(m);
+ }
+ lastbinding = d->binding;
+ }
+ next = d->next;
+ free(d->var);
+ if (d->val != NULL)
+ free(d->val);
+ free(d);
+ }
+ defaults = NULL;
+
+ if (sudoers != NULL)
+ free(sudoers);
+ sudoers = estrdup(path);
+
+ parse_error = FALSE;
+ errorlineno = -1;
+ sudolineno = 1;
+ verbose = !quiet;
+}
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/stat.h>
#include <stdio.h>
#ifdef STDC_HEADERS
# include <stdlib.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif /* HAVE_UNISTD_H */
-#ifdef HAVE_FNMATCH
-# include <fnmatch.h>
-#endif /* HAVE_FNMATCH */
-#ifdef HAVE_EXTENDED_GLOB
-# include <glob.h>
-#endif /* HAVE_EXTENDED_GLOB */
-#ifdef HAVE_NETGROUP_H
-# include <netgroup.h>
-#endif /* HAVE_NETGROUP_H */
#include <ctype.h>
#include <pwd.h>
-#include <grp.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <netdb.h>
-#ifdef HAVE_DIRENT_H
-# include <dirent.h>
-# define NAMLEN(dirent) strlen((dirent)->d_name)
-#else
-# define dirent direct
-# define NAMLEN(dirent) (dirent)->d_namlen
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif
#include "sudo.h"
#include "parse.h"
-#include "interfaces.h"
-
-#ifndef HAVE_FNMATCH
-# include "emul/fnmatch.h"
-#endif /* HAVE_FNMATCH */
-#ifndef HAVE_EXTENDED_GLOB
-# include "emul/glob.h"
-#endif /* HAVE_EXTENDED_GLOB */
+#include "gram.h"
#ifndef lint
static const char rcsid[] = "$Sudo$";
#endif /* lint */
/*
- * Globals
+ * Parsed sudoers info.
*/
-int parse_error = FALSE;
-extern int keepall;
-extern FILE *yyin, *yyout;
+extern struct userspec *userspecs;
/*
- * Prototypes
+ * Parse the specified sudoers file.
*/
-static int has_meta __P((char *));
+int
+parse_sudoers(path)
+ const char *path;
+{
+ extern FILE *yyin;
+
+ yyin = open_sudoers(_PATH_SUDOERS, NULL);
+ init_parser(_PATH_SUDOERS, 0);
+ return(yyparse());
+}
/*
- * Look up the user in the sudoers file and check to see if they are
+ * Look up the user in the parsed sudoers file and check to see if they are
* allowed to run the specified command on this host as the target user.
*/
int
sudoers_lookup(pwflag)
int pwflag;
{
- int error, nopass;
- enum def_tupple pwcheck;
-
- yyin = sudoers_fp;
- yyout = stdout;
-
- /* Allocate space for data structures in the parser. */
- init_parser(_PATH_SUDOERS);
-
- /* If pwcheck *could* be "all" or "any", keep more state. */
- if (pwflag > 0)
- keepall = TRUE;
-
- /* Need to be runas user while stat'ing things in the parser. */
- set_perms(PERM_RUNAS);
- error = yyparse();
- if (error || parse_error) {
- set_perms(PERM_ROOT);
- return(VALIDATE_ERROR);
- }
+ int rval, validated, matched;
+ enum def_tupple pwcheck = 0;
+ struct cmndspec *cs;
+ struct cmndtag *tags = NULL;
+ struct privilege *priv;
+ struct userspec *us;
/*
- * The pw options may have changed during sudoers parse so we
- * wait until now to set this.
+ * We use pwflag to tell us when a password should be required
+ * for pseudo-commands. XXX - pass in pwcheck, not pwflag
*/
if (pwflag)
pwcheck = (pwflag == -1) ? never : sudo_defs_table[pwflag].sd_un.tuple;
- else
- pwcheck = 0;
- /*
- * Assume the worst. If the stack is empty the user was
- * not mentioned at all.
- */
- if (def_authenticate)
- error = VALIDATE_NOT_OK;
- else
- error = VALIDATE_NOT_OK | FLAG_NOPASS;
- if (pwcheck) {
- SET(error, FLAG_NO_CHECK);
- } else {
- SET(error, FLAG_NO_HOST);
- if (!top)
- SET(error, FLAG_NO_USER);
- }
+ /* Assume the worst. */
+ validated = VALIDATE_NOT_OK | FLAG_NO_HOST | FLAG_NO_USER;
+ if (pwflag)
+ SET(validated, FLAG_NO_CHECK);
+ else if (!def_authenticate)
+ validated |= FLAG_NOPASS;
/*
* Only check the actual command if pwflag is not set.
* It is set for the "validate", "list" and "kill" pseudo-commands.
* Always check the host and user.
*/
- nopass = -1;
if (pwflag) {
- int found;
-
- if (pwcheck == always && def_authenticate)
- nopass = FLAG_CHECK_USER;
- else if (pwcheck == never || !def_authenticate)
- nopass = FLAG_NOPASS;
- found = 0;
- while (top) {
- if (host_matches == TRUE) {
- found = 1;
- if (pwcheck == any && no_passwd == TRUE)
- nopass = FLAG_NOPASS;
- else if (pwcheck == all && nopass != 0)
- nopass = (no_passwd == TRUE) ? FLAG_NOPASS : 0;
- }
- top--;
- }
- if (found) {
- set_perms(PERM_ROOT);
- if (nopass == -1)
- nopass = 0;
- return(VALIDATE_OK | nopass);
- }
- } else {
- while (top) {
- if (host_matches == TRUE) {
- CLR(error, FLAG_NO_HOST);
- if (runas_matches == TRUE && cmnd_matches == TRUE) {
- /*
- * User was granted access to cmnd on host as user.
- */
- set_perms(PERM_ROOT);
- return(VALIDATE_OK |
- (no_passwd == TRUE ? FLAG_NOPASS : 0) |
- (no_execve == TRUE ? FLAG_NOEXEC : 0) |
- (monitor_cmnd == TRUE ? FLAG_MONITOR : 0));
- } else if ((runas_matches == TRUE && cmnd_matches == FALSE) ||
- (runas_matches == FALSE && cmnd_matches == TRUE)) {
- /*
- * User was explicitly denied access to cmnd on host.
- */
- set_perms(PERM_ROOT);
- return(VALIDATE_NOT_OK |
- (no_passwd == TRUE ? FLAG_NOPASS : 0) |
- (no_execve == TRUE ? FLAG_NOEXEC : 0) |
- (monitor_cmnd == TRUE ? FLAG_MONITOR : 0));
+ int nopass = UNSPEC;
+
+ CLR(validated, FLAG_NO_USER);
+ CLR(validated, FLAG_NO_HOST);
+ matched = FALSE;
+ for (us = userspecs; us != NULL; us = us->next) {
+ if (user_matches(sudo_user.pw, us->user) == TRUE) {
+ priv = us->privileges;
+ if (host_matches(user_shost, user_host, priv->hostlist) == TRUE) {
+ matched = TRUE;
+ for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
+ if ((pwcheck == any && nopass != TRUE) ||
+ (pwcheck == all && nopass == TRUE))
+ nopass = cs->tags.nopasswd;
+ }
}
}
- top--;
}
- }
- set_perms(PERM_ROOT);
-
- /*
- * The user was neither explicitly granted nor denied access.
- */
- if (nopass == -1)
- nopass = 0;
- return(error | nopass);
-}
-
-/*
- * If path doesn't end in /, return TRUE iff cmnd & path name the same inode;
- * otherwise, return TRUE if user_cmnd names one of the inodes in path.
- */
-int
-command_matches(sudoers_cmnd, sudoers_args)
- char *sudoers_cmnd;
- char *sudoers_args;
-{
- struct stat sudoers_stat;
- struct dirent *dent;
- char **ap, *base, buf[PATH_MAX];
- glob_t gl;
- DIR *dirp;
-
- /* Check for pseudo-commands */
- if (strchr(user_cmnd, '/') == NULL) {
- /*
- * Return true if both sudoers_cmnd and user_cmnd are "sudoedit" AND
- * a) there are no args in sudoers OR
- * b) there are no args on command line and none req by sudoers OR
- * c) there are args in sudoers and on command line and they match
- */
- if (strcmp(sudoers_cmnd, "sudoedit") != 0 ||
- strcmp(user_cmnd, "sudoedit") != 0)
- return(FALSE);
- if (!sudoers_args ||
- (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
- (sudoers_args &&
- fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(sudoers_cmnd);
- return(TRUE);
- } else
- return(FALSE);
- }
-
- /*
- * If sudoers_cmnd has meta characters in it, use fnmatch(3)
- * to do the matching.
- */
- if (has_meta(sudoers_cmnd)) {
- /*
- * Return true if we find a match in the glob(3) results AND
- * a) there are no args in sudoers OR
- * b) there are no args on command line and none required by sudoers OR
- * c) there are args in sudoers and on command line and they match
- * else return false.
- *
- * Could optimize patterns ending in "/*" to "/user_base"
- */
-#define GLOB_FLAGS (GLOB_NOSORT | GLOB_MARK | GLOB_BRACE | GLOB_TILDE)
- if (glob(sudoers_cmnd, GLOB_FLAGS, NULL, &gl) != 0) {
- globfree(&gl);
- return(FALSE);
- }
- /* For each glob match, compare basename, st_dev and st_ino. */
- for (ap = gl.gl_pathv; *ap != NULL; ap++) {
- /* only stat if basenames are the same */
- if ((base = strrchr(*ap, '/')) != NULL)
- base++;
- else
- base = *ap;
- if (strcmp(user_base, base) != 0 ||
- stat(*ap, &sudoers_stat) == -1)
- continue;
- if (user_stat->st_dev == sudoers_stat.st_dev &&
- user_stat->st_ino == sudoers_stat.st_ino) {
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(*ap);
- break;
- }
- }
- globfree(&gl);
- if (*ap == NULL)
- return(FALSE);
-
- if (!sudoers_args ||
- (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
- (sudoers_args &&
- fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(user_cmnd);
- return(TRUE);
- } else
- return(FALSE);
- } else {
- size_t dlen = strlen(sudoers_cmnd);
-
- /*
- * No meta characters
- * Check to make sure this is not a directory spec (doesn't end in '/')
- */
- if (sudoers_cmnd[dlen - 1] != '/') {
- /* Only proceed if user_base and basename(sudoers_cmnd) match */
- if ((base = strrchr(sudoers_cmnd, '/')) == NULL)
- base = sudoers_cmnd;
- else
- base++;
- if (strcmp(user_base, base) != 0 ||
- stat(sudoers_cmnd, &sudoers_stat) == -1)
- return(FALSE);
-
- /*
- * Return true if inode/device matches AND
- * a) there are no args in sudoers OR
- * b) there are no args on command line and none req by sudoers OR
- * c) there are args in sudoers and on command line and they match
- */
- if (user_stat->st_dev != sudoers_stat.st_dev ||
- user_stat->st_ino != sudoers_stat.st_ino)
- return(FALSE);
- if (!sudoers_args ||
- (!user_args && sudoers_args && !strcmp("\"\"", sudoers_args)) ||
- (sudoers_args &&
- fnmatch(sudoers_args, user_args ? user_args : "", 0) == 0)) {
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(sudoers_cmnd);
- return(TRUE);
- } else
- return(FALSE);
+ if (matched == TRUE) {
+ /* User has an entry for this host. */
+ CLR(validated, VALIDATE_NOT_OK);
+ SET(validated, VALIDATE_OK);
+ if (pwcheck == always && def_authenticate)
+ SET(validated, FLAG_CHECK_USER);
+ else if (pwcheck == never || !def_authenticate || nopass == TRUE)
+ SET(validated, FLAG_NOPASS);
}
+ return(validated);
+ }
- /*
- * Grot through sudoers_cmnd's directory entries, looking for user_base.
- */
- dirp = opendir(sudoers_cmnd);
- if (dirp == NULL)
- return(FALSE);
-
- if (strlcpy(buf, sudoers_cmnd, sizeof(buf)) >= sizeof(buf))
- return(FALSE);
- while ((dent = readdir(dirp)) != NULL) {
- /* ignore paths > PATH_MAX (XXX - log) */
- buf[dlen] = '\0';
- if (strlcat(buf, dent->d_name, sizeof(buf)) >= sizeof(buf))
- continue;
+ /* Need to be runas user while stat'ing things. */
+ set_perms(PERM_RUNAS);
- /* only stat if basenames are the same */
- if (strcmp(user_base, dent->d_name) != 0 ||
- stat(buf, &sudoers_stat) == -1)
- continue;
- if (user_stat->st_dev == sudoers_stat.st_dev &&
- user_stat->st_ino == sudoers_stat.st_ino) {
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(buf);
- break;
+ matched = UNSPEC;
+ for (us = userspecs; us != NULL; us = us->next) {
+ if (user_matches(sudo_user.pw, us->user) == TRUE) {
+ CLR(validated, FLAG_NO_USER);
+ priv = us->privileges;
+ if (host_matches(user_shost, user_host, priv->hostlist) == TRUE) {
+ CLR(validated, FLAG_NO_HOST);
+ for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
+ if (runas_matches(runas_pw, cs->runaslist) == TRUE) {
+ rval = cmnd_matches(user_cmnd, user_args, cs->cmnd);
+ if (rval != UNSPEC) {
+ matched = rval;
+ tags = &cs->tags;
+ }
+ }
+ }
}
}
-
- closedir(dirp);
- return(dent != NULL);
}
-}
-
-/*
- * Returns TRUE if "n" is one of our ip addresses or if
- * "n" is a network that we are on, else returns FALSE.
- */
-int
-addr_matches(n)
- char *n;
-{
- int i;
- char *m;
- struct in_addr addr, mask;
-
- /* If there's an explicit netmask, use it. */
- if ((m = strchr(n, '/'))) {
- *m++ = '\0';
- addr.s_addr = inet_addr(n);
- if (strchr(m, '.'))
- mask.s_addr = inet_addr(m);
- else {
- i = 32 - atoi(m);
- mask.s_addr = 0xffffffff;
- mask.s_addr >>= i;
- mask.s_addr <<= i;
- mask.s_addr = htonl(mask.s_addr);
+ if (matched == TRUE) {
+ CLR(validated, VALIDATE_NOT_OK);
+ SET(validated, VALIDATE_OK);
+ if (tags != NULL) {
+ if (tags->nopasswd == TRUE)
+ SET(validated, FLAG_NOPASS);
+ if (tags->noexec == TRUE)
+ SET(validated, FLAG_NOEXEC);
+ if (tags->monitor == TRUE)
+ SET(validated, FLAG_MONITOR);
}
- *(m - 1) = '/';
-
- for (i = 0; i < num_interfaces; i++)
- if ((interfaces[i].addr.s_addr & mask.s_addr) == addr.s_addr)
- return(TRUE);
- } else {
- addr.s_addr = inet_addr(n);
-
- for (i = 0; i < num_interfaces; i++)
- if (interfaces[i].addr.s_addr == addr.s_addr ||
- (interfaces[i].addr.s_addr & interfaces[i].netmask.s_addr)
- == addr.s_addr)
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*
- * Returns 0 if the hostname matches the pattern and non-zero otherwise.
- */
-int
-hostname_matches(shost, lhost, pattern)
- char *shost;
- char *lhost;
- char *pattern;
-{
- if (has_meta(pattern)) {
- if (strchr(pattern, '.'))
- return(fnmatch(pattern, lhost, FNM_CASEFOLD));
- else
- return(fnmatch(pattern, shost, FNM_CASEFOLD));
- } else {
- if (strchr(pattern, '.'))
- return(strcasecmp(lhost, pattern));
- else
- return(strcasecmp(shost, pattern));
- }
-}
-
-/*
- * Returns TRUE if the user/uid from sudoers matches the specified user/uid,
- * else returns FALSE.
- */
-int
-userpw_matches(sudoers_user, user, pw)
- char *sudoers_user;
- char *user;
- struct passwd *pw;
-{
- if (pw != NULL && *sudoers_user == '#') {
- uid_t uid = atoi(sudoers_user + 1);
- if (uid == pw->pw_uid)
- return(1);
}
- return(strcmp(sudoers_user, user) == 0);
+ set_perms(PERM_ROOT);
+ return(validated);
}
/*
- * Returns TRUE if the given user belongs to the named group,
- * else returns FALSE.
- * XXX - reduce the number of passwd/group lookups
+ * Print out privileges for the specified user.
*/
-int
-usergr_matches(group, user, pw)
- char *group;
- char *user;
+void
+display_privs(pw)
struct passwd *pw;
{
- struct group *grp;
- gid_t pw_gid;
- char **cur;
-
- /* make sure we have a valid usergroup, sudo style */
- if (*group++ != '%')
- return(FALSE);
-
- /* look up user's primary gid in the passwd file */
- if (pw == NULL && (pw = getpwnam(user)) == NULL)
- return(FALSE);
- pw_gid = pw->pw_gid;
-
- if ((grp = getgrnam(group)) == NULL)
- return(FALSE);
-
- /* check against user's primary (passwd file) gid */
- if (grp->gr_gid == pw_gid)
- return(TRUE);
-
- /* check to see if user is explicitly listed in the group */
- for (cur = grp->gr_mem; *cur; cur++) {
- if (strcmp(*cur, user) == 0)
- return(TRUE);
- }
-
- return(FALSE);
-}
-
-/*
- * Returns TRUE if "host" and "user" belong to the netgroup "netgr",
- * else return FALSE. Either of "host", "shost" or "user" may be NULL
- * in which case that argument is not checked...
- */
-int
-netgr_matches(netgr, host, shost, user)
- char *netgr;
- char *host;
- char *shost;
- char *user;
-{
-#ifdef HAVE_GETDOMAINNAME
- static char *domain = (char *) -1;
-#else
- static char *domain = NULL;
-#endif /* HAVE_GETDOMAINNAME */
-
- /* make sure we have a valid netgroup, sudo style */
- if (*netgr++ != '+')
- return(FALSE);
-
-#ifdef HAVE_GETDOMAINNAME
- /* get the domain name (if any) */
- if (domain == (char *) -1) {
- domain = (char *) emalloc(MAXHOSTNAMELEN);
- if (getdomainname(domain, MAXHOSTNAMELEN) == -1 || *domain == '\0') {
- free(domain);
- domain = NULL;
+ struct cmndspec *cs;
+ struct member *m, *runas;
+ struct privilege *priv;
+ struct userspec *us;
+
+ printf("User %s may run the following commands on this host:\n",
+ pw->pw_name);
+
+ for (us = userspecs; us != NULL; us = us->next) {
+ if (user_matches(pw, us->user) != TRUE ||
+ host_matches(user_shost, user_host, us->privileges->hostlist) != TRUE)
+ continue;
+
+ priv = us->privileges;
+ runas = NULL;
+ for (cs = priv->cmndlist; cs != NULL; cs = cs->next) {
+ fputs(" ", stdout);
+ if (cs->runaslist != NULL)
+ runas = cs->runaslist;
+ if (runas != NULL) {
+ fputs("(", stdout);
+ for (m = runas; m != NULL; m = m->next) {
+ if (m != runas)
+ fputs(", ", stdout);
+ print_member(m);
+ }
+ fputs(") ", stdout);
+ }
+ if (cs->tags.monitor != UNSPEC && cs->tags.monitor != def_monitor)
+ printf("%sMONITOR: ", cs->tags.monitor ? "" : "NO");
+ if (cs->tags.noexec != UNSPEC && cs->tags.noexec != def_noexec)
+ printf("%sEXEC: ", cs->tags.noexec ? "NO" : "");
+ if (cs->tags.nopasswd != UNSPEC && cs->tags.nopasswd != !def_authenticate)
+ printf("%sPASSWD: ", cs->tags.nopasswd ? "NO" : "");
+ print_member(cs->cmnd);
+ putchar('\n');
}
}
-#endif /* HAVE_GETDOMAINNAME */
-
-#ifdef HAVE_INNETGR
- if (innetgr(netgr, host, user, domain))
- return(TRUE);
- else if (host != shost && innetgr(netgr, shost, user, domain))
- return(TRUE);
-#endif /* HAVE_INNETGR */
-
- return(FALSE);
}
/*
- * Returns TRUE if "s" has shell meta characters in it,
- * else returns FALSE.
+ * Print the contents of a struct member to stdout
*/
-static int
-has_meta(s)
- char *s;
+void
+print_member(m)
+ struct member *m;
{
- char *t;
-
- for (t = s; *t; t++) {
- if (*t == '\\' || *t == '?' || *t == '*' || *t == '[' || *t == ']')
- return(TRUE);
+ struct sudo_command *c;
+
+ if (m->negated)
+ printf("!");
+ if (m->name == NULL)
+ printf("ALL");
+ else if (m->type != COMMAND)
+ printf("%s", m->name);
+ else {
+ c = (struct sudo_command *) m->name;
+ printf("%s%s%s", c->cmnd, c->args ? " " : "",
+ c->args ? c->args : "");
}
- return(FALSE);
}
#ifndef _SUDO_PARSE_H
#define _SUDO_PARSE_H
-/*
- * Data structure used in parsing sudoers;
- * top of stack values are the ones that
- * apply when parsing is done & can be
- * accessed by *_matches macros
- */
-#define STACKINCREMENT (32)
-struct matchstack {
- int user;
- int cmnd;
- int host;
- int runas;
- int nopass;
- int noexec;
- int monitor;
-};
+#undef ALLOW
+#define ALLOW 1
+#undef DENY
+#define DENY 0
+#undef UNSPEC
+#define UNSPEC -1
+/* XXX - use NOTFOUND instead? */
/*
- * Data structure describing a command in the
- * sudoers file.
+ * A command with args. XXX - merge into struct member.
*/
struct sudo_command {
char *cmnd;
char *args;
};
-#define user_matches (match[top-1].user)
-#define cmnd_matches (match[top-1].cmnd)
-#define host_matches (match[top-1].host)
-#define runas_matches (match[top-1].runas)
-#define no_passwd (match[top-1].nopass)
-#define no_execve (match[top-1].noexec)
-#define monitor_cmnd (match[top-1].monitor)
+/*
+ * Tags associated with a command.
+ * Possible valus: TRUE, FALSE, UNSPEC.
+ */
+struct cmndtag {
+ char nopasswd;
+ char noexec;
+ char monitor;
+ char extra;
+};
/*
- * Structure containing command matches if "sudo -l" is used.
+ * The parses sudoers file is stored as a collection of linked lists,
+ * modelled after the yacc grammar.
+ *
+ * There is no separate head struct, the first entry acts as the list head.
+ * Because of this, the "last" field is only valid in the first entry.
+ * The lack of a separate list head structure allows us to avoid keeping
+ * static state in the parser and makes it easy to append sublists.
*/
-struct command_match {
- char *runas;
- size_t runas_len;
- size_t runas_size;
- char *cmnd;
- size_t cmnd_len;
- size_t cmnd_size;
- int nopasswd;
- int noexecve;
- int monitor;
+
+/*
+ * Structure describing a user specification and list thereof.
+ */
+struct userspec {
+ struct member *user; /* list of users */
+ struct privilege *privileges; /* list of privileges */
+ struct userspec *last, *next;
};
/*
- * Structure describing an alias match in parser.
+ * Structure describing a privilege specification.
*/
-typedef struct {
- int type;
- char *name;
- int val;
-} aliasinfo;
+struct privilege {
+ struct member *hostlist; /* list of hosts */
+ struct cmndspec *cmndlist; /* list of Cmnd_Specs */
+ struct privilege *last, *next;
+};
/*
- * Structure containing Cmnd_Alias's if "sudo -l" is used.
+ * Structure describing a linked list of Cmnd_Specs.
*/
-struct generic_alias {
- int type;
- char *alias;
- char *entries;
- size_t entries_size;
- size_t entries_len;
+struct cmndspec {
+ struct member *runaslist; /* list of runas users */
+ struct member *cmnd; /* command to allow/deny */
+ struct cmndtag tags; /* tag specificaion */
+ struct cmndspec *last, *next;
};
-/* The matching stack and number of entries on it. */
-extern struct matchstack *match;
-extern int top;
+/*
+ * Generic structure to hold users, hosts, commands.
+ */
+struct member {
+ char *name; /* member name */
+ short type; /* type (see gram.h) */
+ short negated; /* negated via '!'? */
+ struct member *last, *next;
+};
+
+/*
+ * Generic structure to hold {User,Host,Runas,Cmnd}_Alias
+ */
+struct alias {
+ char *name; /* alias name */
+ int type; /* {USER,HOST,RUNAS,CMND}ALIAS */
+ struct member *first_member; /* list of alias members */
+ struct alias *last, *next;
+};
+
+/*
+ * Structure describing a Defaults entry and a list thereof.
+ */
+struct defaults {
+ char *var; /* variable name */
+ char *val; /* variable value */
+ struct member *binding; /* user/host/runas binding */
+ int type; /* DEFAULTS{,_USER,_RUNAS,_HOST} */
+ int op; /* TRUE, FALSE, '+', '-' */
+ struct defaults *last, *next;
+};
+
+/*
+ * Allocat space for a struct alias and populate it.
+ */
+#define NEW_ALIAS(r, n, t, m) do { \
+ (r) = emalloc(sizeof(struct alias)); \
+ (r)->name = (n); \
+ (r)->type = (t); \
+ (r)->first_member = (m); \
+ (r)->last = NULL; \
+ (r)->next = NULL; \
+} while (0)
+
+/*
+ * Allocat space for a defaults entry and populate it.
+ */
+#define NEW_DEFAULT(r, v1, v2, o) do { \
+ (r) = emalloc(sizeof(struct defaults)); \
+ (r)->var = (v1); \
+ (r)->val = (v2); \
+ (r)->op = (o); \
+ (r)->last = NULL; \
+ (r)->next = NULL; \
+} while (0)
+
+/*
+ * Allocat space for a member and populate it.
+ */
+#define NEW_MEMBER(r, n, t) do { \
+ (r) = emalloc(sizeof(struct member)); \
+ (r)->name = (n); \
+ (r)->type = (t); \
+ (r)->last = NULL; \
+ (r)->next = NULL; \
+} while (0)
+
+/*
+ * Append an entry to the tail of a list.
+ */
+#define LIST_APPEND(h, e) do { \
+ if ((h)->last != NULL) \
+ (h)->last->next = (e); \
+ else /* if ((h)->next == NULL) */ \
+ (h)->next = (e); \
+ (h)->last = (e); \
+} while (0)
/*
* Prototypes
*/
int addr_matches __P((char *));
+int alias_matches __P((char *, int, VOID *, VOID *));
+int cmnd_matches __P((char *, char *, struct member *));
int command_matches __P((char *, char *));
+int host_matches __P((char *, char *, struct member *));
int hostname_matches __P((char *, char *, char *));
int netgr_matches __P((char *, char *, char *, char *));
-int userpw_matches __P((char *, char *, struct passwd *));
+int runas_matches __P((struct passwd *, struct member *));
+int user_matches __P((struct passwd *, struct member *));
int usergr_matches __P((char *, char *, struct passwd *));
-void init_parser __P((char *));
+int userpw_matches __P((char *, char *, struct passwd *));
+void init_parser __P((char *, int));
+void print_member __P((struct member *m));
#endif /* _SUDO_PARSE_H */
+++ /dev/null
-%{
-/*
- * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-
-/*
- * XXX - the whole opFOO naming thing is somewhat bogus.
- *
- * XXX - the way things are stored for printmatches is stupid,
- * they should be stored as elements in an array and then
- * list_matches() can format things the way it wants.
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <stdio.h>
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif /* STDC_HEADERS */
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-# include <strings.h>
-# endif
-#endif /* HAVE_STRING_H */
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <pwd.h>
-#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
-# include <malloc.h>
-#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
-#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-# include <alloca.h>
-#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
-#ifdef HAVE_LSEARCH
-# include <search.h>
-#endif /* HAVE_LSEARCH */
-
-#include "sudo.h"
-#include "parse.h"
-
-#ifndef HAVE_LSEARCH
-#include "emul/search.h"
-#endif /* HAVE_LSEARCH */
-
-#ifndef lint
-static const char rcsid[] = "$Sudo$";
-#endif /* lint */
-
-/*
- * Globals
- */
-extern int sudolineno, parse_error;
-extern char *sudoers;
-int clearaliases = TRUE;
-int printmatches = FALSE;
-int pedantic = FALSE;
-int keepall = FALSE;
-int quiet = FALSE;
-int used_runas = FALSE;
-int errorlineno = -1;
-char *errorfile = NULL;
-
-/*
- * Alias types
- */
-#define HOST_ALIAS 1
-#define CMND_ALIAS 2
-#define USER_ALIAS 3
-#define RUNAS_ALIAS 4
-
-#define SETMATCH(_var, _val) do { \
- if ((_var) == UNSPEC || (_val) != NOMATCH) \
- (_var) = (_val); \
-} while (0)
-
-#define SETNMATCH(_var, _val) do { \
- if ((_val) != NOMATCH) \
- (_var) = ! (_val); \
- else if ((_var) == UNSPEC) \
- (_var) = NOMATCH; \
-} while (0)
-
-/*
- * The matching stack, initial space allocated in init_parser().
- */
-struct matchstack *match;
-int top = 0, stacksize = 0;
-
-#define push \
- do { \
- if (top >= stacksize) { \
- while ((stacksize += STACKINCREMENT) < top); \
- match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \
- } \
- match[top].user = UNSPEC; \
- match[top].cmnd = UNSPEC; \
- match[top].host = UNSPEC; \
- match[top].runas = UNSPEC; \
- match[top].nopass = def_authenticate ? UNSPEC : TRUE; \
- match[top].noexec = def_noexec ? TRUE : UNSPEC; \
- match[top].monitor = def_monitor ? TRUE : UNSPEC; \
- top++; \
- } while (0)
-
-#define pushcp \
- do { \
- if (top >= stacksize) { \
- while ((stacksize += STACKINCREMENT) < top); \
- match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \
- } \
- match[top].user = match[top-1].user; \
- match[top].cmnd = match[top-1].cmnd; \
- match[top].host = match[top-1].host; \
- match[top].runas = match[top-1].runas; \
- match[top].nopass = match[top-1].nopass; \
- match[top].noexec = match[top-1].noexec; \
- match[top].monitor = match[top-1].monitor; \
- top++; \
- } while (0)
-
-#define pop \
- do { \
- if (top == 0) \
- yyerror("matching stack underflow"); \
- else \
- top--; \
- } while (0)
-
-
-/*
- * For testing if foo_matches variable was set to TRUE or FALSE
- */
-#define MATCHED(_v) ((_v) >= 0)
-
-/*
- * Shortcuts for append()
- */
-#define append_cmnd(s, p) append(s, &cm_list[cm_list_len].cmnd, \
- &cm_list[cm_list_len].cmnd_len, &cm_list[cm_list_len].cmnd_size, p)
-
-#define append_runas(s, p) append(s, &cm_list[cm_list_len].runas, \
- &cm_list[cm_list_len].runas_len, &cm_list[cm_list_len].runas_size, p)
-
-#define append_entries(s, p) append(s, &ga_list[ga_list_len-1].entries, \
- &ga_list[ga_list_len-1].entries_len, \
- &ga_list[ga_list_len-1].entries_size, p)
-
-/*
- * The stack for printmatches. A list of allowed commands for the user.
- */
-static struct command_match *cm_list = NULL;
-static size_t cm_list_len = 0, cm_list_size = 0;
-
-/*
- * List of Cmnd_Aliases and expansions for `sudo -l'
- */
-static int in_alias = FALSE;
-static size_t ga_list_len = 0, ga_list_size = 0;
-static struct generic_alias *ga_list = NULL;
-
-/*
- * Does this Defaults list pertain to this user?
- */
-static int defaults_matches = FALSE;
-
-/*
- * Local protoypes
- */
-static int add_alias __P((char *, int, int));
-static void append __P((char *, char **, size_t *, size_t *, char *));
-static void expand_ga_list __P((void));
-static void expand_match_list __P((void));
-static aliasinfo *find_alias __P((char *, int));
-static int more_aliases __P((void));
- void yyerror __P((const char *));
-
-void
-yyerror(s)
- const char *s;
-{
- /* Save the line the first error occurred on. */
- if (errorlineno == -1) {
- errorlineno = sudolineno ? sudolineno - 1 : 0;
- errorfile = estrdup(sudoers);
- }
- if (s && !quiet) {
-#ifndef TRACELEXER
- (void) fprintf(stderr, ">>> %s: %s, line %d <<<\n", sudoers, s,
- sudolineno ? sudolineno - 1 : 0);
-#else
- (void) fprintf(stderr, "<*> ");
-#endif
- }
- parse_error = TRUE;
-}
-%}
-
-%union {
- char *string;
- int BOOLEAN;
- struct sudo_command command;
- int tok;
-}
-
-%start file /* special start symbol */
-%token <command> COMMAND /* absolute pathname w/ optional args */
-%token <string> ALIAS /* an UPPERCASE alias name */
-%token <string> DEFVAR /* a Defaults variable name */
-%token <string> NTWKADDR /* w.x.y.z */
-%token <string> NETGROUP /* a netgroup (+NAME) */
-%token <string> USERGROUP /* a usergroup (%NAME) */
-%token <string> WORD /* a word */
-%token <tok> DEFAULTS /* Defaults entry */
-%token <tok> DEFAULTS_HOST /* Host-specific defaults entry */
-%token <tok> DEFAULTS_USER /* User-specific defaults entry */
-%token <tok> DEFAULTS_RUNAS /* Runas-specific defaults entry */
-%token <tok> RUNAS /* ( runas_list ) */
-%token <tok> NOPASSWD /* no passwd req for command */
-%token <tok> PASSWD /* passwd req for command (default) */
-%token <tok> NOEXEC /* preload dummy execve() for cmnd */
-%token <tok> EXEC /* don't preload dummy execve() */
-%token <tok> MONITOR /* monitor children of cmnd */
-%token <tok> NOMONITOR /* disable monitoring of children */
-%token <tok> ALL /* ALL keyword */
-%token <tok> COMMENT /* comment and/or carriage return */
-%token <tok> HOSTALIAS /* Host_Alias keyword */
-%token <tok> CMNDALIAS /* Cmnd_Alias keyword */
-%token <tok> USERALIAS /* User_Alias keyword */
-%token <tok> RUNASALIAS /* Runas_Alias keyword */
-%token <tok> ':' '=' ',' '!' '+' '-' /* union member tokens */
-%token <tok> ERROR
-
-/*
- * NOTE: these are not true booleans as there are actually 4 possible values:
- * 1) TRUE (positive match)
- * 0) FALSE (negative match due to a '!' somewhere)
- * -1) NOMATCH (don't change the value of *_matches)
- * -2) UNSPEC (uninitialized value)
- */
-%type <BOOLEAN> cmnd
-%type <BOOLEAN> host
-%type <BOOLEAN> runasuser
-%type <BOOLEAN> oprunasuser
-%type <BOOLEAN> runaslist
-%type <BOOLEAN> user
-
-%%
-
-file : { ; }
- | line
- ;
-
-line : entry
- | line entry
- ;
-
-entry : COMMENT
- { ; }
- | error COMMENT
- { yyerrok; }
- | { push; } userlist privileges {
- while (top && user_matches != TRUE)
- pop;
- }
- | USERALIAS useraliases
- { ; }
- | HOSTALIAS hostaliases
- { ; }
- | CMNDALIAS cmndaliases
- { ; }
- | RUNASALIAS runasaliases
- { ; }
- | defaults_line
- { ; }
- ;
-
-defaults_line : defaults_type defaults_list
- ;
-
-defaults_type : DEFAULTS {
- defaults_matches = TRUE;
- }
- | DEFAULTS_USER { push; } userlist {
- defaults_matches = user_matches;
- pop;
- }
- | DEFAULTS_RUNAS { push; } runaslist {
- defaults_matches = $3 == TRUE;
- pop;
- }
- | DEFAULTS_HOST { push; } hostlist {
- defaults_matches = host_matches;
- pop;
- }
- ;
-
-defaults_list : defaults_entry
- | defaults_entry ',' defaults_list
- ;
-
-defaults_entry : DEFVAR {
- if (defaults_matches == TRUE &&
- !set_default($1, NULL, TRUE)) {
- yyerror(NULL);
- YYERROR;
- }
- free($1);
- }
- | '!' DEFVAR {
- if (defaults_matches == TRUE &&
- !set_default($2, NULL, FALSE)) {
- yyerror(NULL);
- YYERROR;
- }
- free($2);
- }
- | DEFVAR '=' WORD {
- if (defaults_matches == TRUE &&
- !set_default($1, $3, TRUE)) {
- yyerror(NULL);
- YYERROR;
- }
- free($1);
- free($3);
- }
- | DEFVAR '+' WORD {
- if (defaults_matches == TRUE &&
- !set_default($1, $3, '+')) {
- yyerror(NULL);
- YYERROR;
- }
- free($1);
- free($3);
- }
- | DEFVAR '-' WORD {
- if (defaults_matches == TRUE &&
- !set_default($1, $3, '-')) {
- yyerror(NULL);
- YYERROR;
- }
- free($1);
- free($3);
- }
- ;
-
-privileges : privilege
- | privileges ':' privilege
- ;
-
-privilege : hostlist '=' cmndspeclist {
- /*
- * We already did a push if necessary in
- * cmndspec so just reset some values so
- * the next 'privilege' gets a clean slate.
- */
- host_matches = UNSPEC;
- runas_matches = UNSPEC;
- no_passwd = def_authenticate ? UNSPEC : TRUE;
- no_execve = def_noexec ? TRUE : UNSPEC;
- monitor_cmnd = def_monitor ? TRUE : UNSPEC;
- }
- ;
-
-ophost : host {
- SETMATCH(host_matches, $1);
- }
- | '!' host {
- SETNMATCH(host_matches, $2);
- }
- ;
-
-host : ALL {
- $$ = TRUE;
- }
- | NTWKADDR {
- if (addr_matches($1))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | NETGROUP {
- if (netgr_matches($1, user_host, user_shost, NULL))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | WORD {
- if (hostname_matches(user_shost, user_host, $1) == 0)
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | ALIAS {
- aliasinfo *aip = find_alias($1, HOST_ALIAS);
-
- /* could be an all-caps hostname */
- if (aip)
- $$ = aip->val;
- else if (strcasecmp(user_shost, $1) == 0)
- $$ = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Host_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", $1, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- $$ = NOMATCH;
- }
- free($1);
- }
- ;
-
-cmndspeclist : cmndspec
- | cmndspeclist ',' cmndspec
- ;
-
-cmndspec : runasspec cmndtag opcmnd {
- /*
- * Push the entry onto the stack if it is worth
- * saving and reset cmnd_matches for next cmnd.
- *
- * We need to save at least one entry on
- * the stack so sudoers_lookup() can tell that
- * the user was listed in sudoers. Also, we
- * need to be able to tell whether or not a
- * user was listed for this specific host.
- *
- * If keepall is set and the user matches then
- * we need to keep entries around too...
- */
- if (MATCHED(user_matches) &&
- MATCHED(host_matches) &&
- MATCHED(cmnd_matches) &&
- MATCHED(runas_matches))
- pushcp;
- else if (MATCHED(user_matches) && (top == 1 ||
- (top == 2 && MATCHED(host_matches) &&
- !MATCHED(match[0].host))))
- pushcp;
- else if (user_matches == TRUE && keepall)
- pushcp;
- cmnd_matches = UNSPEC;
- }
- ;
-
-opcmnd : cmnd {
- SETMATCH(cmnd_matches, $1);
- }
- | '!' {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("!", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_cmnd("!", NULL);
- }
- } cmnd {
- SETNMATCH(cmnd_matches, $3);
- }
- ;
-
-runasspec : /* empty */ {
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE) {
- if (runas_matches == UNSPEC) {
- cm_list[cm_list_len].runas_len = 0;
- } else {
- /* Inherit runas data. */
- cm_list[cm_list_len].runas =
- estrdup(cm_list[cm_list_len-1].runas);
- cm_list[cm_list_len].runas_len =
- cm_list[cm_list_len-1].runas_len;
- cm_list[cm_list_len].runas_size =
- cm_list[cm_list_len-1].runas_size;
- }
- }
- /*
- * If this is the first entry in a command list
- * then check against default runas user.
- */
- if (runas_matches == UNSPEC) {
- runas_matches =
- userpw_matches(def_runas_default,
- *user_runas, runas_pw);
- }
- }
- | RUNAS runaslist {
- runas_matches = $2;
- }
- ;
-
-runaslist : oprunasuser { ; }
- | runaslist ',' oprunasuser {
- /* Later entries override earlier ones. */
- if ($3 != NOMATCH)
- $$ = $3;
- else
- $$ = $1;
- }
- ;
-
-oprunasuser : runasuser { ; }
- | '!' {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("!", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas("!", ", ");
- }
- } runasuser {
- /* Set $$ to the negation of runasuser */
- $$ = ($3 == NOMATCH ? NOMATCH : ! $3);
- }
- ;
-
-runasuser : WORD {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries($1, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas($1, ", ");
- }
- if (userpw_matches($1, *user_runas, runas_pw))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- used_runas = TRUE;
- }
- | USERGROUP {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries($1, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas($1, ", ");
- }
- if (usergr_matches($1, *user_runas, runas_pw))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- used_runas = TRUE;
- }
- | NETGROUP {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries($1, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas($1, ", ");
- }
- if (netgr_matches($1, NULL, NULL, *user_runas))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- used_runas = TRUE;
- }
- | ALIAS {
- aliasinfo *aip = find_alias($1, RUNAS_ALIAS);
-
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries($1, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas($1, ", ");
- }
- /* could be an all-caps username */
- if (aip)
- $$ = aip->val;
- else if (strcmp($1, *user_runas) == 0)
- $$ = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Runas_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", $1, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- $$ = NOMATCH;
- }
- free($1);
- used_runas = TRUE;
- }
- | ALL {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("ALL", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas("ALL", ", ");
- }
- $$ = TRUE;
- }
- ;
-
-cmndtag : /* empty */ {
- /* Inherit tags. */
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE) {
- if (no_passwd == TRUE)
- cm_list[cm_list_len].nopasswd = TRUE;
- else
- cm_list[cm_list_len].nopasswd = FALSE;
- if (no_execve == TRUE)
- cm_list[cm_list_len].noexecve = TRUE;
- else
- cm_list[cm_list_len].noexecve = FALSE;
- if (monitor_cmnd == TRUE)
- cm_list[cm_list_len].monitor = TRUE;
- else
- cm_list[cm_list_len].monitor = FALSE;
- }
- }
- | cmndtag NOPASSWD {
- no_passwd = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].nopasswd = TRUE;
- }
- | cmndtag PASSWD {
- no_passwd = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].nopasswd = FALSE;
- }
- | cmndtag NOEXEC {
- no_execve = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].noexecve = TRUE;
- }
- | cmndtag EXEC {
- no_execve = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].noexecve = FALSE;
- }
- | cmndtag MONITOR {
- monitor_cmnd = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].monitor = TRUE;
- }
- | cmndtag NOMONITOR {
- monitor_cmnd = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].monitor = FALSE;
- }
- ;
-
-cmnd : ALL {
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("ALL", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd("ALL", NULL);
- expand_match_list();
- }
- }
-
- $$ = TRUE;
-
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(user_cmnd);
- }
- | ALIAS {
- aliasinfo *aip;
-
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries($1, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd($1, NULL);
- expand_match_list();
- }
- }
-
- if ((aip = find_alias($1, CMND_ALIAS)))
- $$ = aip->val;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Cmnd_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", $1, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- $$ = NOMATCH;
- }
- free($1);
- }
- | COMMAND {
- if (printmatches == TRUE) {
- if (in_alias == TRUE) {
- append_entries($1.cmnd, ", ");
- if ($1.args)
- append_entries($1.args, " ");
- }
- if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd($1.cmnd, NULL);
- if ($1.args)
- append_cmnd($1.args, " ");
- expand_match_list();
- }
- }
-
- if (command_matches($1.cmnd, $1.args))
- $$ = TRUE;
- else
- $$ = NOMATCH;
-
- free($1.cmnd);
- if ($1.args)
- free($1.args);
- }
- ;
-
-hostaliases : hostalias
- | hostaliases ':' hostalias
- ;
-
-hostalias : ALIAS { push; } '=' hostlist {
- if ((MATCHED(host_matches) || pedantic) &&
- !add_alias($1, HOST_ALIAS, host_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- }
- ;
-
-hostlist : ophost
- | hostlist ',' ophost
- ;
-
-cmndaliases : cmndalias
- | cmndaliases ':' cmndalias
- ;
-
-cmndalias : ALIAS {
- push;
- if (printmatches == TRUE) {
- in_alias = TRUE;
- /* Allocate space for ga_list if necessary. */
- expand_ga_list();
- ga_list[ga_list_len-1].type = CMND_ALIAS;
- ga_list[ga_list_len-1].alias = estrdup($1);
- }
- } '=' cmndlist {
- if ((MATCHED(cmnd_matches) || pedantic) &&
- !add_alias($1, CMND_ALIAS, cmnd_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- free($1);
-
- if (printmatches == TRUE)
- in_alias = FALSE;
- }
- ;
-
-cmndlist : opcmnd { ; }
- | cmndlist ',' opcmnd
- ;
-
-runasaliases : runasalias
- | runasaliases ':' runasalias
- ;
-
-runasalias : ALIAS {
- if (printmatches == TRUE) {
- in_alias = TRUE;
- /* Allocate space for ga_list if necessary. */
- expand_ga_list();
- ga_list[ga_list_len-1].type = RUNAS_ALIAS;
- ga_list[ga_list_len-1].alias = estrdup($1);
- }
- } '=' runaslist {
- if (($4 != NOMATCH || pedantic) &&
- !add_alias($1, RUNAS_ALIAS, $4)) {
- yyerror(NULL);
- YYERROR;
- }
- free($1);
-
- if (printmatches == TRUE)
- in_alias = FALSE;
- }
- ;
-
-useraliases : useralias
- | useraliases ':' useralias
- ;
-
-useralias : ALIAS { push; } '=' userlist {
- if ((MATCHED(user_matches) || pedantic) &&
- !add_alias($1, USER_ALIAS, user_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- free($1);
- }
- ;
-
-userlist : opuser
- | userlist ',' opuser
- ;
-
-opuser : user {
- SETMATCH(user_matches, $1);
- }
- | '!' user {
- SETNMATCH(user_matches, $2);
- }
- ;
-
-user : WORD {
- if (userpw_matches($1, user_name, sudo_user.pw))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | USERGROUP {
- if (usergr_matches($1, user_name, sudo_user.pw))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | NETGROUP {
- if (netgr_matches($1, NULL, NULL, user_name))
- $$ = TRUE;
- else
- $$ = NOMATCH;
- free($1);
- }
- | ALIAS {
- aliasinfo *aip = find_alias($1, USER_ALIAS);
-
- /* could be an all-caps username */
- if (aip)
- $$ = aip->val;
- else if (strcmp($1, user_name) == 0)
- $$ = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared User_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", $1, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- $$ = NOMATCH;
- }
- free($1);
- }
- | ALL {
- $$ = TRUE;
- }
- ;
-
-%%
-
-#define MOREALIASES (32)
-aliasinfo *aliases = NULL;
-size_t naliases = 0;
-size_t nslots = 0;
-
-
-/*
- * Compare two aliasinfo structures, strcmp() style.
- * Note that we do *not* compare their values.
- */
-static int
-aliascmp(a1, a2)
- const VOID *a1, *a2;
-{
- int r;
- aliasinfo *ai1, *ai2;
-
- ai1 = (aliasinfo *) a1;
- ai2 = (aliasinfo *) a2;
- if ((r = strcmp(ai1->name, ai2->name)) == 0)
- r = ai1->type - ai2->type;
-
- return(r);
-}
-
-/*
- * Compare two generic_alias structures, strcmp() style.
- */
-static int
-genaliascmp(entry, key)
- const VOID *entry, *key;
-{
- int r;
- struct generic_alias *ga1, *ga2;
-
- ga1 = (struct generic_alias *) key;
- ga2 = (struct generic_alias *) entry;
- if ((r = strcmp(ga1->alias, ga2->alias)) == 0)
- r = ga1->type - ga2->type;
-
- return(r);
-}
-
-
-/*
- * Adds the named alias of the specified type to the aliases list.
- */
-static int
-add_alias(alias, type, val)
- char *alias;
- int type;
- int val;
-{
- aliasinfo ai, *aip;
- size_t onaliases;
- char s[512];
-
- if (naliases >= nslots && !more_aliases()) {
- (void) snprintf(s, sizeof(s), "Out of memory defining alias `%s'",
- alias);
- yyerror(s);
- return(FALSE);
- }
-
- ai.type = type;
- ai.val = val;
- ai.name = estrdup(alias);
- onaliases = naliases;
-
- aip = (aliasinfo *) lsearch((VOID *)&ai, (VOID *)aliases, &naliases,
- sizeof(ai), aliascmp);
- if (aip == NULL) {
- (void) snprintf(s, sizeof(s), "Aliases corrupted defining alias `%s'",
- alias);
- yyerror(s);
- return(FALSE);
- }
- if (onaliases == naliases) {
- (void) snprintf(s, sizeof(s), "Alias `%s' already defined", alias);
- yyerror(s);
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-/*
- * Searches for the named alias of the specified type.
- */
-static aliasinfo *
-find_alias(alias, type)
- char *alias;
- int type;
-{
- aliasinfo ai;
-
- ai.name = alias;
- ai.type = type;
-
- return((aliasinfo *) lfind((VOID *)&ai, (VOID *)aliases, &naliases,
- sizeof(ai), aliascmp));
-}
-
-/*
- * Allocates more space for the aliases list.
- */
-static int
-more_aliases()
-{
-
- nslots += MOREALIASES;
- if (nslots == MOREALIASES)
- aliases = (aliasinfo *) malloc(nslots * sizeof(aliasinfo));
- else
- aliases = (aliasinfo *) realloc(aliases, nslots * sizeof(aliasinfo));
-
- return(aliases != NULL);
-}
-
-/*
- * Lists the contents of the aliases list.
- */
-void
-dumpaliases()
-{
- size_t n;
-
- for (n = 0; n < naliases; n++) {
- if (aliases[n].val == -1)
- continue;
-
- switch (aliases[n].type) {
- case HOST_ALIAS:
- (void) puts("HOST_ALIAS");
- break;
-
- case CMND_ALIAS:
- (void) puts("CMND_ALIAS");
- break;
-
- case USER_ALIAS:
- (void) puts("USER_ALIAS");
- break;
-
- case RUNAS_ALIAS:
- (void) puts("RUNAS_ALIAS");
- break;
- }
- (void) printf("\t%s: %d\n", aliases[n].name, aliases[n].val);
- }
-}
-
-/*
- * Lists the contents of cm_list and ga_list for `sudo -l'.
- */
-void
-list_matches()
-{
- size_t count;
- char *p;
- struct generic_alias *ga, key;
-
- (void) printf("User %s may run the following commands on this host:\n",
- user_name);
- for (count = 0; count < cm_list_len; count++) {
-
- /* Print the runas list. */
- (void) fputs(" ", stdout);
- if (cm_list[count].runas) {
- (void) putchar('(');
- p = strtok(cm_list[count].runas, ", ");
- do {
- if (p != cm_list[count].runas)
- (void) fputs(", ", stdout);
-
- key.alias = p;
- key.type = RUNAS_ALIAS;
- if ((ga = (struct generic_alias *) lfind((VOID *) &key,
- (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp)))
- (void) fputs(ga->entries, stdout);
- else
- (void) fputs(p, stdout);
- } while ((p = strtok(NULL, ", ")));
- (void) fputs(") ", stdout);
- } else {
- (void) printf("(%s) ", def_runas_default);
- }
-
- /* Is execve(2) disabled? */
- if (cm_list[count].noexecve == TRUE && !def_noexec)
- (void) fputs("NOEXEC: ", stdout);
- else if (cm_list[count].noexecve == FALSE && def_noexec)
- (void) fputs("EXEC: ", stdout);
-
- /* Is monitoring enabled? */
- if (cm_list[count].monitor == TRUE && !def_monitor)
- (void) fputs("MONITOR: ", stdout);
- else if (cm_list[count].monitor == FALSE && def_monitor)
- (void) fputs("NOMONITOR: ", stdout);
-
- /* Is a password required? */
- if (cm_list[count].nopasswd == TRUE && def_authenticate)
- (void) fputs("NOPASSWD: ", stdout);
- else if (cm_list[count].nopasswd == FALSE && !def_authenticate)
- (void) fputs("PASSWD: ", stdout);
-
- /* Print the actual command or expanded Cmnd_Alias. */
- key.alias = cm_list[count].cmnd;
- key.type = CMND_ALIAS;
- if ((ga = (struct generic_alias *) lfind((VOID *) &key,
- (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp)))
- (void) puts(ga->entries);
- else
- (void) puts(cm_list[count].cmnd);
- }
-
- /* Be nice and free up space now that we are done. */
- for (count = 0; count < ga_list_len; count++) {
- free(ga_list[count].alias);
- free(ga_list[count].entries);
- }
- free(ga_list);
- ga_list = NULL;
-
- for (count = 0; count < cm_list_len; count++) {
- free(cm_list[count].runas);
- free(cm_list[count].cmnd);
- }
- free(cm_list);
- cm_list = NULL;
- cm_list_len = 0;
- cm_list_size = 0;
-}
-
-/*
- * Appends a source string to the destination, optionally prefixing a separator.
- */
-static void
-append(src, dstp, dst_len, dst_size, separator)
- char *src, **dstp;
- size_t *dst_len, *dst_size;
- char *separator;
-{
- size_t src_len = strlen(src);
- char *dst = *dstp;
-
- /*
- * Only add the separator if there is something to separate from.
- * If the last char is a '!', don't apply the separator (XXX).
- */
- if (separator && dst && dst[*dst_len - 1] != '!')
- src_len += strlen(separator);
- else
- separator = NULL;
-
- /* Assumes dst will be NULL if not set. */
- if (dst == NULL) {
- dst = (char *) emalloc(BUFSIZ);
- *dst = '\0';
- *dst_size = BUFSIZ;
- *dst_len = 0;
- *dstp = dst;
- }
-
- /* Allocate more space if necessary. */
- if (*dst_size <= *dst_len + src_len) {
- while (*dst_size <= *dst_len + src_len)
- *dst_size += BUFSIZ;
-
- dst = (char *) erealloc(dst, *dst_size);
- *dstp = dst;
- }
-
- /* Copy src -> dst adding a separator if appropriate and adjust len. */
- if (separator)
- (void) strlcat(dst, separator, *dst_size);
- (void) strlcat(dst, src, *dst_size);
- *dst_len += src_len;
-}
-
-/*
- * Frees up space used by the aliases list and resets the associated counters.
- */
-void
-reset_aliases()
-{
- size_t n;
-
- if (aliases) {
- for (n = 0; n < naliases; n++)
- free(aliases[n].name);
- free(aliases);
- aliases = NULL;
- }
- naliases = nslots = 0;
-}
-
-/*
- * Increments ga_list_len, allocating more space as necessary.
- */
-static void
-expand_ga_list()
-{
-
- if (++ga_list_len >= ga_list_size) {
- while ((ga_list_size += STACKINCREMENT) < ga_list_len)
- ;
- ga_list = (struct generic_alias *)
- erealloc3(ga_list, ga_list_size, sizeof(struct generic_alias));
- }
-
- ga_list[ga_list_len - 1].entries = NULL;
-}
-
-/*
- * Increments cm_list_len, allocating more space as necessary.
- */
-static void
-expand_match_list()
-{
-
- if (++cm_list_len >= cm_list_size) {
- while ((cm_list_size += STACKINCREMENT) < cm_list_len)
- ;
- if (cm_list == NULL)
- cm_list_len = 0; /* start at 0 since it is a subscript */
- cm_list = (struct command_match *)
- erealloc3(cm_list, cm_list_size, sizeof(struct command_match));
- }
-
- cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL;
- cm_list[cm_list_len].nopasswd = FALSE;
- cm_list[cm_list_len].noexecve = FALSE;
- cm_list[cm_list_len].monitor = FALSE;
-}
-
-/*
- * Frees up spaced used by a previous parser run and allocates new space
- * for various data structures.
- */
-void
-init_parser(path)
- char *path;
-{
-
- /* Free up old data structures if we run the parser more than once. */
- if (match) {
- free(match);
- match = NULL;
- top = 0;
- parse_error = FALSE;
- used_runas = FALSE;
- errorlineno = -1;
- sudolineno = 1;
- free(sudoers);
- }
-
- /* Allocate space for the matching stack. */
- stacksize = STACKINCREMENT;
- match = (struct matchstack *) emalloc2(stacksize, sizeof(struct matchstack));
-
- /* Allocate space for the match list (for `sudo -l'). */
- if (printmatches == TRUE)
- expand_match_list();
-
- sudoers = estrdup(path);
-}
+++ /dev/null
-#ifndef lint
-/*static char yysccsid[] = "from: @(#)yaccpar 1.9 (Berkeley) 02/21/93";*/
-static char yyrcsid[]
-#if __GNUC__ >= 2
- __attribute__ ((unused))
-#endif /* __GNUC__ >= 2 */
- = "$OpenBSD: skeleton.c,v 1.23 2004/03/12 13:39:50 henning Exp $";
-#endif
-#include <stdlib.h>
-#define YYBYACC 1
-#define YYMAJOR 1
-#define YYMINOR 9
-#define YYLEX yylex()
-#define YYEMPTY -1
-#define yyclearin (yychar=(YYEMPTY))
-#define yyerrok (yyerrflag=0)
-#define YYRECOVERING() (yyerrflag!=0)
-#define YYPREFIX "yy"
-#line 2 "parse.yacc"
-/*
- * Copyright (c) 1996, 1998-2004 Todd C. Miller <Todd.Miller@courtesan.com>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- * Sponsored in part by the Defense Advanced Research Projects
- * Agency (DARPA) and Air Force Research Laboratory, Air Force
- * Materiel Command, USAF, under agreement number F39502-99-1-0512.
- */
-
-/*
- * XXX - the whole opFOO naming thing is somewhat bogus.
- *
- * XXX - the way things are stored for printmatches is stupid,
- * they should be stored as elements in an array and then
- * list_matches() can format things the way it wants.
- */
-
-#include "config.h"
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <stdio.h>
-#ifdef STDC_HEADERS
-# include <stdlib.h>
-# include <stddef.h>
-#else
-# ifdef HAVE_STDLIB_H
-# include <stdlib.h>
-# endif
-#endif /* STDC_HEADERS */
-#ifdef HAVE_STRING_H
-# include <string.h>
-#else
-# ifdef HAVE_STRINGS_H
-# include <strings.h>
-# endif
-#endif /* HAVE_STRING_H */
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#include <pwd.h>
-#if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
-# include <malloc.h>
-#endif /* HAVE_MALLOC_H && !STDC_HEADERS */
-#if defined(YYBISON) && defined(HAVE_ALLOCA_H) && !defined(__GNUC__)
-# include <alloca.h>
-#endif /* YYBISON && HAVE_ALLOCA_H && !__GNUC__ */
-#ifdef HAVE_LSEARCH
-# include <search.h>
-#endif /* HAVE_LSEARCH */
-
-#include "sudo.h"
-#include "parse.h"
-
-#ifndef HAVE_LSEARCH
-#include "emul/search.h"
-#endif /* HAVE_LSEARCH */
-
-#ifndef lint
-static const char rcsid[] = "$Sudo$";
-#endif /* lint */
-
-/*
- * Globals
- */
-extern int sudolineno, parse_error;
-extern char *sudoers;
-int clearaliases = TRUE;
-int printmatches = FALSE;
-int pedantic = FALSE;
-int keepall = FALSE;
-int quiet = FALSE;
-int used_runas = FALSE;
-int errorlineno = -1;
-char *errorfile = NULL;
-
-/*
- * Alias types
- */
-#define HOST_ALIAS 1
-#define CMND_ALIAS 2
-#define USER_ALIAS 3
-#define RUNAS_ALIAS 4
-
-#define SETMATCH(_var, _val) do { \
- if ((_var) == UNSPEC || (_val) != NOMATCH) \
- (_var) = (_val); \
-} while (0)
-
-#define SETNMATCH(_var, _val) do { \
- if ((_val) != NOMATCH) \
- (_var) = ! (_val); \
- else if ((_var) == UNSPEC) \
- (_var) = NOMATCH; \
-} while (0)
-
-/*
- * The matching stack, initial space allocated in init_parser().
- */
-struct matchstack *match;
-int top = 0, stacksize = 0;
-
-#define push \
- do { \
- if (top >= stacksize) { \
- while ((stacksize += STACKINCREMENT) < top); \
- match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \
- } \
- match[top].user = UNSPEC; \
- match[top].cmnd = UNSPEC; \
- match[top].host = UNSPEC; \
- match[top].runas = UNSPEC; \
- match[top].nopass = def_authenticate ? UNSPEC : TRUE; \
- match[top].noexec = def_noexec ? TRUE : UNSPEC; \
- match[top].monitor = def_monitor ? TRUE : UNSPEC; \
- top++; \
- } while (0)
-
-#define pushcp \
- do { \
- if (top >= stacksize) { \
- while ((stacksize += STACKINCREMENT) < top); \
- match = (struct matchstack *) erealloc3(match, stacksize, sizeof(struct matchstack)); \
- } \
- match[top].user = match[top-1].user; \
- match[top].cmnd = match[top-1].cmnd; \
- match[top].host = match[top-1].host; \
- match[top].runas = match[top-1].runas; \
- match[top].nopass = match[top-1].nopass; \
- match[top].noexec = match[top-1].noexec; \
- match[top].monitor = match[top-1].monitor; \
- top++; \
- } while (0)
-
-#define pop \
- do { \
- if (top == 0) \
- yyerror("matching stack underflow"); \
- else \
- top--; \
- } while (0)
-
-
-/*
- * For testing if foo_matches variable was set to TRUE or FALSE
- */
-#define MATCHED(_v) ((_v) >= 0)
-
-/*
- * Shortcuts for append()
- */
-#define append_cmnd(s, p) append(s, &cm_list[cm_list_len].cmnd, \
- &cm_list[cm_list_len].cmnd_len, &cm_list[cm_list_len].cmnd_size, p)
-
-#define append_runas(s, p) append(s, &cm_list[cm_list_len].runas, \
- &cm_list[cm_list_len].runas_len, &cm_list[cm_list_len].runas_size, p)
-
-#define append_entries(s, p) append(s, &ga_list[ga_list_len-1].entries, \
- &ga_list[ga_list_len-1].entries_len, \
- &ga_list[ga_list_len-1].entries_size, p)
-
-/*
- * The stack for printmatches. A list of allowed commands for the user.
- */
-static struct command_match *cm_list = NULL;
-static size_t cm_list_len = 0, cm_list_size = 0;
-
-/*
- * List of Cmnd_Aliases and expansions for `sudo -l'
- */
-static int in_alias = FALSE;
-static size_t ga_list_len = 0, ga_list_size = 0;
-static struct generic_alias *ga_list = NULL;
-
-/*
- * Does this Defaults list pertain to this user?
- */
-static int defaults_matches = FALSE;
-
-/*
- * Local protoypes
- */
-static int add_alias __P((char *, int, int));
-static void append __P((char *, char **, size_t *, size_t *, char *));
-static void expand_ga_list __P((void));
-static void expand_match_list __P((void));
-static aliasinfo *find_alias __P((char *, int));
-static int more_aliases __P((void));
- void yyerror __P((const char *));
-
-void
-yyerror(s)
- const char *s;
-{
- /* Save the line the first error occurred on. */
- if (errorlineno == -1) {
- errorlineno = sudolineno ? sudolineno - 1 : 0;
- errorfile = estrdup(sudoers);
- }
- if (s && !quiet) {
-#ifndef TRACELEXER
- (void) fprintf(stderr, ">>> %s: %s, line %d <<<\n", sudoers, s,
- sudolineno ? sudolineno - 1 : 0);
-#else
- (void) fprintf(stderr, "<*> ");
-#endif
- }
- parse_error = TRUE;
-}
-#line 226 "parse.yacc"
-#ifndef YYSTYPE_DEFINED
-#define YYSTYPE_DEFINED
-typedef union {
- char *string;
- int BOOLEAN;
- struct sudo_command command;
- int tok;
-} YYSTYPE;
-#endif /* YYSTYPE_DEFINED */
-#line 253 "sudo.tab.c"
-#define COMMAND 257
-#define ALIAS 258
-#define DEFVAR 259
-#define NTWKADDR 260
-#define NETGROUP 261
-#define USERGROUP 262
-#define WORD 263
-#define DEFAULTS 264
-#define DEFAULTS_HOST 265
-#define DEFAULTS_USER 266
-#define DEFAULTS_RUNAS 267
-#define RUNAS 268
-#define NOPASSWD 269
-#define PASSWD 270
-#define NOEXEC 271
-#define EXEC 272
-#define MONITOR 273
-#define NOMONITOR 274
-#define ALL 275
-#define COMMENT 276
-#define HOSTALIAS 277
-#define CMNDALIAS 278
-#define USERALIAS 279
-#define RUNASALIAS 280
-#define ERROR 281
-#define YYERRCODE 256
-#if defined(__cplusplus) || defined(__STDC__)
-const short yylhs[] =
-#else
-short yylhs[] =
-#endif
- { -1,
- 0, 0, 7, 7, 8, 8, 10, 8, 8, 8,
- 8, 8, 8, 16, 17, 19, 17, 20, 17, 22,
- 17, 18, 18, 23, 23, 23, 23, 23, 11, 11,
- 24, 26, 26, 2, 2, 2, 2, 2, 25, 25,
- 27, 30, 31, 30, 28, 28, 5, 5, 4, 32,
- 4, 3, 3, 3, 3, 3, 29, 29, 29, 29,
- 29, 29, 29, 1, 1, 1, 13, 13, 34, 33,
- 21, 21, 14, 14, 36, 35, 37, 37, 15, 15,
- 39, 38, 12, 12, 41, 40, 9, 9, 42, 42,
- 6, 6, 6, 6, 6,
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yylen[] =
-#else
-short yylen[] =
-#endif
- { 2,
- 0, 1, 1, 2, 1, 2, 0, 3, 2, 2,
- 2, 2, 1, 2, 1, 0, 3, 0, 3, 0,
- 3, 1, 3, 1, 2, 3, 3, 3, 1, 3,
- 3, 1, 2, 1, 1, 1, 1, 1, 1, 3,
- 3, 1, 0, 3, 0, 2, 1, 3, 1, 0,
- 3, 1, 1, 1, 1, 1, 0, 2, 2, 2,
- 2, 2, 2, 1, 1, 1, 1, 3, 0, 4,
- 1, 3, 1, 3, 0, 4, 1, 3, 1, 3,
- 0, 4, 1, 3, 0, 4, 1, 3, 1, 2,
- 1, 1, 1, 1, 1,
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yydefred[] =
-#else
-short yydefred[] =
-#endif
- { 0,
- 0, 15, 20, 16, 18, 5, 0, 0, 0, 0,
- 0, 0, 3, 0, 13, 0, 6, 0, 0, 0,
- 69, 0, 67, 75, 0, 73, 85, 0, 83, 81,
- 0, 79, 4, 94, 93, 92, 91, 95, 0, 89,
- 0, 87, 0, 0, 14, 0, 38, 35, 36, 37,
- 34, 0, 32, 0, 71, 0, 55, 54, 53, 52,
- 56, 50, 49, 47, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 90, 0, 0, 0, 29, 0, 0,
- 0, 25, 0, 33, 0, 0, 0, 0, 68, 0,
- 74, 0, 84, 0, 80, 88, 0, 0, 26, 27,
- 28, 23, 72, 51, 48, 0, 66, 65, 64, 43,
- 42, 77, 0, 0, 0, 30, 0, 0, 39, 57,
- 0, 0, 0, 0, 0, 44, 78, 40, 58, 59,
- 60, 61, 62, 63, 41,
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yydgoto[] =
-#else
-short yydgoto[] =
-#endif
- { 11,
- 111, 53, 63, 64, 65, 40, 12, 13, 41, 14,
- 76, 28, 22, 25, 31, 15, 16, 45, 19, 20,
- 77, 18, 46, 78, 118, 55, 119, 120, 125, 112,
- 121, 86, 23, 66, 26, 68, 113, 32, 72, 29,
- 70, 42,
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yysindex[] =
-#else
-short yysindex[] =
-#endif
- { -229,
- -256, 0, 0, 0, 0, 0, -237, -234, -226, -225,
- 0, -229, 0, 114, 0, -33, 0, 140, 114, 166,
- 0, -12, 0, 0, -5, 0, 0, -4, 0, 0,
- -1, 0, 0, 0, 0, 0, 0, 0, -244, 0,
- -28, 0, -36, -216, 0, 11, 0, 0, 0, 0,
- 0, -219, 0, 14, 0, 17, 0, 0, 0, 0,
- 0, 0, 0, 0, 22, 6, -237, 7, -234, 8,
- -226, 9, -225, 0, 114, 13, -21, 0, -191, -189,
- -187, 0, -33, 0, 140, -198, 166, 140, 0, 276,
- 0, 114, 0, 166, 0, 0, 140, -188, 0, 0,
- 0, 0, 0, 0, 0, 14, 0, 0, 0, 0,
- 0, 0, 35, 17, 22, 0, 166, 37, 0, 0,
- -247, 276, 22, -188, -29, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yyrindex[] =
-#else
-short yyrindex[] =
-#endif
- { 62,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 88, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 156, 0, 0, 181, 0, 0, 206, 0, 0,
- 236, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 1, 0, 0, 261, 0, 0, 0, 0,
- 0, 0, 0, -25, 0, -11, 0, 0, 0, 0,
- 0, 0, 0, 0, -3, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 300, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, -20, 0, 0,
- 0, 0, 0, 0, 0, 26, 0, 0, 0, 0,
- 0, 0, 52, 78, 104, 0, 0, 130, 0, 0,
- 0, 0, 274, -20, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0,};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yygindex[] =
-#else
-short yygindex[] =
-#endif
- { 0,
- -39, 31, 3, 4, -88, 47, 0, 75, -17, 0,
- 0, 0, 0, 0, 0, 0, 0, 10, 0, 0,
- -15, 0, 0, -7, 0, 12, -32, 0, 0, -110,
- 0, 0, 27, 0, 29, 0, 0, 23, 0, 28,
- 0, 25,
-};
-#define YYTABLESIZE 580
-#if defined(__cplusplus) || defined(__STDC__)
-const short yytable[] =
-#else
-short yytable[] =
-#endif
- { 44,
- 24, 56, 54, 110, 52, 115, 80, 21, 81, 107,
- 108, 127, 45, 34, 135, 75, 35, 36, 37, 17,
- 21, 17, 85, 24, 79, 70, 1, 109, 123, 19,
- 38, 27, 30, 24, 2, 3, 4, 5, 47, 98,
- 48, 49, 82, 50, 24, 67, 6, 7, 8, 9,
- 10, 76, 69, 71, 83, 51, 73, 85, 70, 57,
- 75, 1, 58, 59, 60, 87, 88, 90, 92, 94,
- 97, 99, 106, 100, 114, 101, 61, 86, 122, 117,
- 124, 126, 84, 70, 76, 74, 33, 2, 104, 116,
- 105, 128, 102, 89, 7, 95, 103, 91, 93, 96,
- 0, 0, 0, 82, 0, 0, 0, 0, 0, 76,
- 86, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 7, 0, 0, 0, 0, 0, 0, 0, 0, 31,
- 0, 0, 0, 0, 0, 86, 82, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 39, 0, 0, 0,
- 0, 0, 0, 0, 0, 10, 0, 0, 0, 0,
- 0, 82, 31, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 52, 0, 0, 0, 0, 0, 0, 0,
- 11, 0, 0, 0, 0, 0, 0, 31, 10, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 62, 0,
- 0, 0, 0, 0, 0, 9, 0, 0, 0, 0,
- 0, 0, 0, 11, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 43, 0, 107, 108, 47,
- 0, 48, 49, 21, 50, 12, 45, 45, 9, 129,
- 130, 131, 132, 133, 134, 109, 51, 17, 45, 45,
- 45, 45, 45, 45, 45, 19, 24, 0, 24, 0,
- 22, 24, 24, 24, 24, 24, 24, 24, 12, 0,
- 0, 0, 0, 0, 0, 24, 24, 24, 24, 24,
- 24, 70, 0, 70, 0, 0, 70, 70, 70, 70,
- 70, 70, 70, 22, 0, 0, 0, 0, 0, 8,
- 70, 70, 70, 70, 70, 70, 46, 76, 110, 76,
- 0, 0, 76, 76, 76, 76, 76, 76, 76, 7,
- 0, 0, 7, 7, 7, 0, 76, 76, 76, 76,
- 76, 76, 8, 86, 0, 86, 7, 0, 86, 86,
- 86, 86, 86, 86, 86, 7, 0, 0, 7, 7,
- 7, 0, 86, 86, 86, 86, 86, 86, 0, 82,
- 0, 82, 7, 0, 82, 82, 82, 82, 82, 82,
- 82, 34, 0, 0, 35, 36, 37, 0, 82, 82,
- 82, 82, 82, 82, 0, 31, 0, 31, 38, 0,
- 31, 31, 31, 31, 31, 31, 31, 47, 0, 48,
- 49, 0, 50, 0, 31, 31, 31, 31, 31, 31,
- 0, 10, 0, 10, 51, 0, 10, 10, 10, 10,
- 10, 10, 10, 57, 0, 0, 58, 59, 60, 0,
- 10, 10, 10, 10, 10, 10, 11, 0, 11, 0,
- 61, 11, 11, 11, 11, 11, 11, 11, 0, 0,
- 0, 0, 0, 0, 0, 11, 11, 11, 11, 11,
- 11, 9, 0, 9, 0, 0, 9, 9, 9, 9,
- 9, 9, 9, 0, 0, 0, 0, 0, 0, 0,
- 9, 9, 9, 9, 9, 9, 0, 0, 0, 0,
- 0, 12, 0, 12, 0, 0, 12, 12, 12, 12,
- 12, 12, 12, 0, 0, 0, 0, 0, 0, 0,
- 12, 12, 12, 12, 12, 12, 22, 0, 22, 0,
- 0, 22, 22, 22, 22, 22, 22, 22, 0, 0,
- 46, 46, 107, 108, 0, 22, 22, 22, 22, 22,
- 22, 0, 46, 46, 46, 46, 46, 46, 46, 0,
- 109, 0, 0, 0, 0, 8, 0, 8, 0, 0,
- 8, 8, 8, 8, 8, 8, 8, 0, 0, 0,
- 0, 0, 0, 0, 8, 8, 8, 8, 8, 8,
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const short yycheck[] =
-#else
-short yycheck[] =
-#endif
- { 33,
- 0, 19, 18, 33, 33, 94, 43, 33, 45, 257,
- 258, 122, 33, 258, 125, 44, 261, 262, 263, 276,
- 258, 33, 44, 258, 61, 0, 256, 275, 117, 33,
- 275, 258, 258, 33, 264, 265, 266, 267, 258, 61,
- 260, 261, 259, 263, 44, 58, 276, 277, 278, 279,
- 280, 0, 58, 58, 44, 275, 58, 44, 33, 258,
- 44, 0, 261, 262, 263, 44, 61, 61, 61, 61,
- 58, 263, 88, 263, 92, 263, 275, 0, 44, 268,
- 44, 121, 52, 58, 33, 39, 12, 0, 86, 97,
- 87, 124, 83, 67, 33, 73, 85, 69, 71, 75,
- -1, -1, -1, 0, -1, -1, -1, -1, -1, 58,
- 33, -1, -1, -1, -1, -1, -1, -1, -1, -1,
- 33, -1, -1, -1, -1, -1, -1, -1, -1, 0,
- -1, -1, -1, -1, -1, 58, 33, -1, -1, -1,
- -1, -1, -1, -1, -1, -1, 33, -1, -1, -1,
- -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
- -1, 58, 33, -1, -1, -1, -1, -1, -1, -1,
- -1, -1, 33, -1, -1, -1, -1, -1, -1, -1,
- 0, -1, -1, -1, -1, -1, -1, 58, 33, -1,
- -1, -1, -1, -1, -1, -1, -1, -1, 33, -1,
- -1, -1, -1, -1, -1, 0, -1, -1, -1, -1,
- -1, -1, -1, 33, -1, -1, -1, -1, -1, -1,
- -1, -1, -1, -1, -1, 259, -1, 257, 258, 258,
- -1, 260, 261, 259, 263, 0, 257, 258, 33, 269,
- 270, 271, 272, 273, 274, 275, 275, 259, 269, 270,
- 271, 272, 273, 274, 275, 259, 256, -1, 258, -1,
- 0, 261, 262, 263, 264, 265, 266, 267, 33, -1,
- -1, -1, -1, -1, -1, 275, 276, 277, 278, 279,
- 280, 256, -1, 258, -1, -1, 261, 262, 263, 264,
- 265, 266, 267, 33, -1, -1, -1, -1, -1, 0,
- 275, 276, 277, 278, 279, 280, 33, 256, 33, 258,
- -1, -1, 261, 262, 263, 264, 265, 266, 267, 258,
- -1, -1, 261, 262, 263, -1, 275, 276, 277, 278,
- 279, 280, 33, 256, -1, 258, 275, -1, 261, 262,
- 263, 264, 265, 266, 267, 258, -1, -1, 261, 262,
- 263, -1, 275, 276, 277, 278, 279, 280, -1, 256,
- -1, 258, 275, -1, 261, 262, 263, 264, 265, 266,
- 267, 258, -1, -1, 261, 262, 263, -1, 275, 276,
- 277, 278, 279, 280, -1, 256, -1, 258, 275, -1,
- 261, 262, 263, 264, 265, 266, 267, 258, -1, 260,
- 261, -1, 263, -1, 275, 276, 277, 278, 279, 280,
- -1, 256, -1, 258, 275, -1, 261, 262, 263, 264,
- 265, 266, 267, 258, -1, -1, 261, 262, 263, -1,
- 275, 276, 277, 278, 279, 280, 256, -1, 258, -1,
- 275, 261, 262, 263, 264, 265, 266, 267, -1, -1,
- -1, -1, -1, -1, -1, 275, 276, 277, 278, 279,
- 280, 256, -1, 258, -1, -1, 261, 262, 263, 264,
- 265, 266, 267, -1, -1, -1, -1, -1, -1, -1,
- 275, 276, 277, 278, 279, 280, -1, -1, -1, -1,
- -1, 256, -1, 258, -1, -1, 261, 262, 263, 264,
- 265, 266, 267, -1, -1, -1, -1, -1, -1, -1,
- 275, 276, 277, 278, 279, 280, 256, -1, 258, -1,
- -1, 261, 262, 263, 264, 265, 266, 267, -1, -1,
- 257, 258, 257, 258, -1, 275, 276, 277, 278, 279,
- 280, -1, 269, 270, 271, 272, 273, 274, 275, -1,
- 275, -1, -1, -1, -1, 256, -1, 258, -1, -1,
- 261, 262, 263, 264, 265, 266, 267, -1, -1, -1,
- -1, -1, -1, -1, 275, 276, 277, 278, 279, 280,
-};
-#define YYFINAL 11
-#ifndef YYDEBUG
-#define YYDEBUG 0
-#endif
-#define YYMAXTOKEN 281
-#if YYDEBUG
-#if defined(__cplusplus) || defined(__STDC__)
-const char * const yyname[] =
-#else
-char *yyname[] =
-#endif
- {
-"end-of-file",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-"'!'",0,0,0,0,0,0,0,0,0,"'+'","','","'-'",0,0,0,0,0,0,0,0,0,0,0,0,"':'",0,0,
-"'='",0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
-"COMMAND","ALIAS","DEFVAR","NTWKADDR","NETGROUP","USERGROUP","WORD","DEFAULTS",
-"DEFAULTS_HOST","DEFAULTS_USER","DEFAULTS_RUNAS","RUNAS","NOPASSWD","PASSWD",
-"NOEXEC","EXEC","MONITOR","NOMONITOR","ALL","COMMENT","HOSTALIAS","CMNDALIAS",
-"USERALIAS","RUNASALIAS","ERROR",
-};
-#if defined(__cplusplus) || defined(__STDC__)
-const char * const yyrule[] =
-#else
-char *yyrule[] =
-#endif
- {"$accept : file",
-"file :",
-"file : line",
-"line : entry",
-"line : line entry",
-"entry : COMMENT",
-"entry : error COMMENT",
-"$$1 :",
-"entry : $$1 userlist privileges",
-"entry : USERALIAS useraliases",
-"entry : HOSTALIAS hostaliases",
-"entry : CMNDALIAS cmndaliases",
-"entry : RUNASALIAS runasaliases",
-"entry : defaults_line",
-"defaults_line : defaults_type defaults_list",
-"defaults_type : DEFAULTS",
-"$$2 :",
-"defaults_type : DEFAULTS_USER $$2 userlist",
-"$$3 :",
-"defaults_type : DEFAULTS_RUNAS $$3 runaslist",
-"$$4 :",
-"defaults_type : DEFAULTS_HOST $$4 hostlist",
-"defaults_list : defaults_entry",
-"defaults_list : defaults_entry ',' defaults_list",
-"defaults_entry : DEFVAR",
-"defaults_entry : '!' DEFVAR",
-"defaults_entry : DEFVAR '=' WORD",
-"defaults_entry : DEFVAR '+' WORD",
-"defaults_entry : DEFVAR '-' WORD",
-"privileges : privilege",
-"privileges : privileges ':' privilege",
-"privilege : hostlist '=' cmndspeclist",
-"ophost : host",
-"ophost : '!' host",
-"host : ALL",
-"host : NTWKADDR",
-"host : NETGROUP",
-"host : WORD",
-"host : ALIAS",
-"cmndspeclist : cmndspec",
-"cmndspeclist : cmndspeclist ',' cmndspec",
-"cmndspec : runasspec cmndtag opcmnd",
-"opcmnd : cmnd",
-"$$5 :",
-"opcmnd : '!' $$5 cmnd",
-"runasspec :",
-"runasspec : RUNAS runaslist",
-"runaslist : oprunasuser",
-"runaslist : runaslist ',' oprunasuser",
-"oprunasuser : runasuser",
-"$$6 :",
-"oprunasuser : '!' $$6 runasuser",
-"runasuser : WORD",
-"runasuser : USERGROUP",
-"runasuser : NETGROUP",
-"runasuser : ALIAS",
-"runasuser : ALL",
-"cmndtag :",
-"cmndtag : cmndtag NOPASSWD",
-"cmndtag : cmndtag PASSWD",
-"cmndtag : cmndtag NOEXEC",
-"cmndtag : cmndtag EXEC",
-"cmndtag : cmndtag MONITOR",
-"cmndtag : cmndtag NOMONITOR",
-"cmnd : ALL",
-"cmnd : ALIAS",
-"cmnd : COMMAND",
-"hostaliases : hostalias",
-"hostaliases : hostaliases ':' hostalias",
-"$$7 :",
-"hostalias : ALIAS $$7 '=' hostlist",
-"hostlist : ophost",
-"hostlist : hostlist ',' ophost",
-"cmndaliases : cmndalias",
-"cmndaliases : cmndaliases ':' cmndalias",
-"$$8 :",
-"cmndalias : ALIAS $$8 '=' cmndlist",
-"cmndlist : opcmnd",
-"cmndlist : cmndlist ',' opcmnd",
-"runasaliases : runasalias",
-"runasaliases : runasaliases ':' runasalias",
-"$$9 :",
-"runasalias : ALIAS $$9 '=' runaslist",
-"useraliases : useralias",
-"useraliases : useraliases ':' useralias",
-"$$10 :",
-"useralias : ALIAS $$10 '=' userlist",
-"userlist : opuser",
-"userlist : userlist ',' opuser",
-"opuser : user",
-"opuser : '!' user",
-"user : WORD",
-"user : USERGROUP",
-"user : NETGROUP",
-"user : ALIAS",
-"user : ALL",
-};
-#endif
-#ifdef YYSTACKSIZE
-#undef YYMAXDEPTH
-#define YYMAXDEPTH YYSTACKSIZE
-#else
-#ifdef YYMAXDEPTH
-#define YYSTACKSIZE YYMAXDEPTH
-#else
-#define YYSTACKSIZE 10000
-#define YYMAXDEPTH 10000
-#endif
-#endif
-#define YYINITSTACKSIZE 200
-int yydebug;
-int yynerrs;
-int yyerrflag;
-int yychar;
-short *yyssp;
-YYSTYPE *yyvsp;
-YYSTYPE yyval;
-YYSTYPE yylval;
-short *yyss;
-short *yysslim;
-YYSTYPE *yyvs;
-int yystacksize;
-#line 918 "parse.yacc"
-
-#define MOREALIASES (32)
-aliasinfo *aliases = NULL;
-size_t naliases = 0;
-size_t nslots = 0;
-
-
-/*
- * Compare two aliasinfo structures, strcmp() style.
- * Note that we do *not* compare their values.
- */
-static int
-aliascmp(a1, a2)
- const VOID *a1, *a2;
-{
- int r;
- aliasinfo *ai1, *ai2;
-
- ai1 = (aliasinfo *) a1;
- ai2 = (aliasinfo *) a2;
- if ((r = strcmp(ai1->name, ai2->name)) == 0)
- r = ai1->type - ai2->type;
-
- return(r);
-}
-
-/*
- * Compare two generic_alias structures, strcmp() style.
- */
-static int
-genaliascmp(entry, key)
- const VOID *entry, *key;
-{
- int r;
- struct generic_alias *ga1, *ga2;
-
- ga1 = (struct generic_alias *) key;
- ga2 = (struct generic_alias *) entry;
- if ((r = strcmp(ga1->alias, ga2->alias)) == 0)
- r = ga1->type - ga2->type;
-
- return(r);
-}
-
-
-/*
- * Adds the named alias of the specified type to the aliases list.
- */
-static int
-add_alias(alias, type, val)
- char *alias;
- int type;
- int val;
-{
- aliasinfo ai, *aip;
- size_t onaliases;
- char s[512];
-
- if (naliases >= nslots && !more_aliases()) {
- (void) snprintf(s, sizeof(s), "Out of memory defining alias `%s'",
- alias);
- yyerror(s);
- return(FALSE);
- }
-
- ai.type = type;
- ai.val = val;
- ai.name = estrdup(alias);
- onaliases = naliases;
-
- aip = (aliasinfo *) lsearch((VOID *)&ai, (VOID *)aliases, &naliases,
- sizeof(ai), aliascmp);
- if (aip == NULL) {
- (void) snprintf(s, sizeof(s), "Aliases corrupted defining alias `%s'",
- alias);
- yyerror(s);
- return(FALSE);
- }
- if (onaliases == naliases) {
- (void) snprintf(s, sizeof(s), "Alias `%s' already defined", alias);
- yyerror(s);
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-/*
- * Searches for the named alias of the specified type.
- */
-static aliasinfo *
-find_alias(alias, type)
- char *alias;
- int type;
-{
- aliasinfo ai;
-
- ai.name = alias;
- ai.type = type;
-
- return((aliasinfo *) lfind((VOID *)&ai, (VOID *)aliases, &naliases,
- sizeof(ai), aliascmp));
-}
-
-/*
- * Allocates more space for the aliases list.
- */
-static int
-more_aliases()
-{
-
- nslots += MOREALIASES;
- if (nslots == MOREALIASES)
- aliases = (aliasinfo *) malloc(nslots * sizeof(aliasinfo));
- else
- aliases = (aliasinfo *) realloc(aliases, nslots * sizeof(aliasinfo));
-
- return(aliases != NULL);
-}
-
-/*
- * Lists the contents of the aliases list.
- */
-void
-dumpaliases()
-{
- size_t n;
-
- for (n = 0; n < naliases; n++) {
- if (aliases[n].val == -1)
- continue;
-
- switch (aliases[n].type) {
- case HOST_ALIAS:
- (void) puts("HOST_ALIAS");
- break;
-
- case CMND_ALIAS:
- (void) puts("CMND_ALIAS");
- break;
-
- case USER_ALIAS:
- (void) puts("USER_ALIAS");
- break;
-
- case RUNAS_ALIAS:
- (void) puts("RUNAS_ALIAS");
- break;
- }
- (void) printf("\t%s: %d\n", aliases[n].name, aliases[n].val);
- }
-}
-
-/*
- * Lists the contents of cm_list and ga_list for `sudo -l'.
- */
-void
-list_matches()
-{
- size_t count;
- char *p;
- struct generic_alias *ga, key;
-
- (void) printf("User %s may run the following commands on this host:\n",
- user_name);
- for (count = 0; count < cm_list_len; count++) {
-
- /* Print the runas list. */
- (void) fputs(" ", stdout);
- if (cm_list[count].runas) {
- (void) putchar('(');
- p = strtok(cm_list[count].runas, ", ");
- do {
- if (p != cm_list[count].runas)
- (void) fputs(", ", stdout);
-
- key.alias = p;
- key.type = RUNAS_ALIAS;
- if ((ga = (struct generic_alias *) lfind((VOID *) &key,
- (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp)))
- (void) fputs(ga->entries, stdout);
- else
- (void) fputs(p, stdout);
- } while ((p = strtok(NULL, ", ")));
- (void) fputs(") ", stdout);
- } else {
- (void) printf("(%s) ", def_runas_default);
- }
-
- /* Is execve(2) disabled? */
- if (cm_list[count].noexecve == TRUE && !def_noexec)
- (void) fputs("NOEXEC: ", stdout);
- else if (cm_list[count].noexecve == FALSE && def_noexec)
- (void) fputs("EXEC: ", stdout);
-
- /* Is monitoring enabled? */
- if (cm_list[count].monitor == TRUE && !def_monitor)
- (void) fputs("MONITOR: ", stdout);
- else if (cm_list[count].monitor == FALSE && def_monitor)
- (void) fputs("NOMONITOR: ", stdout);
-
- /* Is a password required? */
- if (cm_list[count].nopasswd == TRUE && def_authenticate)
- (void) fputs("NOPASSWD: ", stdout);
- else if (cm_list[count].nopasswd == FALSE && !def_authenticate)
- (void) fputs("PASSWD: ", stdout);
-
- /* Print the actual command or expanded Cmnd_Alias. */
- key.alias = cm_list[count].cmnd;
- key.type = CMND_ALIAS;
- if ((ga = (struct generic_alias *) lfind((VOID *) &key,
- (VOID *) &ga_list[0], &ga_list_len, sizeof(key), genaliascmp)))
- (void) puts(ga->entries);
- else
- (void) puts(cm_list[count].cmnd);
- }
-
- /* Be nice and free up space now that we are done. */
- for (count = 0; count < ga_list_len; count++) {
- free(ga_list[count].alias);
- free(ga_list[count].entries);
- }
- free(ga_list);
- ga_list = NULL;
-
- for (count = 0; count < cm_list_len; count++) {
- free(cm_list[count].runas);
- free(cm_list[count].cmnd);
- }
- free(cm_list);
- cm_list = NULL;
- cm_list_len = 0;
- cm_list_size = 0;
-}
-
-/*
- * Appends a source string to the destination, optionally prefixing a separator.
- */
-static void
-append(src, dstp, dst_len, dst_size, separator)
- char *src, **dstp;
- size_t *dst_len, *dst_size;
- char *separator;
-{
- size_t src_len = strlen(src);
- char *dst = *dstp;
-
- /*
- * Only add the separator if there is something to separate from.
- * If the last char is a '!', don't apply the separator (XXX).
- */
- if (separator && dst && dst[*dst_len - 1] != '!')
- src_len += strlen(separator);
- else
- separator = NULL;
-
- /* Assumes dst will be NULL if not set. */
- if (dst == NULL) {
- dst = (char *) emalloc(BUFSIZ);
- *dst = '\0';
- *dst_size = BUFSIZ;
- *dst_len = 0;
- *dstp = dst;
- }
-
- /* Allocate more space if necessary. */
- if (*dst_size <= *dst_len + src_len) {
- while (*dst_size <= *dst_len + src_len)
- *dst_size += BUFSIZ;
-
- dst = (char *) erealloc(dst, *dst_size);
- *dstp = dst;
- }
-
- /* Copy src -> dst adding a separator if appropriate and adjust len. */
- if (separator)
- (void) strlcat(dst, separator, *dst_size);
- (void) strlcat(dst, src, *dst_size);
- *dst_len += src_len;
-}
-
-/*
- * Frees up space used by the aliases list and resets the associated counters.
- */
-void
-reset_aliases()
-{
- size_t n;
-
- if (aliases) {
- for (n = 0; n < naliases; n++)
- free(aliases[n].name);
- free(aliases);
- aliases = NULL;
- }
- naliases = nslots = 0;
-}
-
-/*
- * Increments ga_list_len, allocating more space as necessary.
- */
-static void
-expand_ga_list()
-{
-
- if (++ga_list_len >= ga_list_size) {
- while ((ga_list_size += STACKINCREMENT) < ga_list_len)
- ;
- ga_list = (struct generic_alias *)
- erealloc3(ga_list, ga_list_size, sizeof(struct generic_alias));
- }
-
- ga_list[ga_list_len - 1].entries = NULL;
-}
-
-/*
- * Increments cm_list_len, allocating more space as necessary.
- */
-static void
-expand_match_list()
-{
-
- if (++cm_list_len >= cm_list_size) {
- while ((cm_list_size += STACKINCREMENT) < cm_list_len)
- ;
- if (cm_list == NULL)
- cm_list_len = 0; /* start at 0 since it is a subscript */
- cm_list = (struct command_match *)
- erealloc3(cm_list, cm_list_size, sizeof(struct command_match));
- }
-
- cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL;
- cm_list[cm_list_len].nopasswd = FALSE;
- cm_list[cm_list_len].noexecve = FALSE;
- cm_list[cm_list_len].monitor = FALSE;
-}
-
-/*
- * Frees up spaced used by a previous parser run and allocates new space
- * for various data structures.
- */
-void
-init_parser(path)
- char *path;
-{
-
- /* Free up old data structures if we run the parser more than once. */
- if (match) {
- free(match);
- match = NULL;
- top = 0;
- parse_error = FALSE;
- used_runas = FALSE;
- errorlineno = -1;
- sudolineno = 1;
- free(sudoers);
- }
-
- /* Allocate space for the matching stack. */
- stacksize = STACKINCREMENT;
- match = (struct matchstack *) emalloc2(stacksize, sizeof(struct matchstack));
-
- /* Allocate space for the match list (for `sudo -l'). */
- if (printmatches == TRUE)
- expand_match_list();
-
- sudoers = estrdup(path);
-}
-#line 998 "sudo.tab.c"
-/* allocate initial stack or double stack size, up to YYMAXDEPTH */
-#if defined(__cplusplus) || defined(__STDC__)
-static int yygrowstack(void)
-#else
-static int yygrowstack()
-#endif
-{
- int newsize, i;
- short *newss;
- YYSTYPE *newvs;
-
- if ((newsize = yystacksize) == 0)
- newsize = YYINITSTACKSIZE;
- else if (newsize >= YYMAXDEPTH)
- return -1;
- else if ((newsize *= 2) > YYMAXDEPTH)
- newsize = YYMAXDEPTH;
- i = yyssp - yyss;
- newss = yyss ? (short *)realloc(yyss, newsize * sizeof *newss) :
- (short *)malloc(newsize * sizeof *newss);
- if (newss == NULL)
- goto bail;
- yyss = newss;
- yyssp = newss + i;
- newvs = yyvs ? (YYSTYPE *)realloc(yyvs, newsize * sizeof *newvs) :
- (YYSTYPE *)malloc(newsize * sizeof *newvs);
- if (newvs == NULL)
- goto bail;
- yyvs = newvs;
- yyvsp = newvs + i;
- yystacksize = newsize;
- yysslim = yyss + newsize - 1;
- return 0;
-bail:
- if (yyss)
- free(yyss);
- if (yyvs)
- free(yyvs);
- yyss = yyssp = NULL;
- yyvs = yyvsp = NULL;
- yystacksize = 0;
- return -1;
-}
-
-#define YYABORT goto yyabort
-#define YYREJECT goto yyabort
-#define YYACCEPT goto yyaccept
-#define YYERROR goto yyerrlab
-int
-#if defined(__cplusplus) || defined(__STDC__)
-yyparse(void)
-#else
-yyparse()
-#endif
-{
- int yym, yyn, yystate;
-#if YYDEBUG
-#if defined(__cplusplus) || defined(__STDC__)
- const char *yys;
-#else /* !(defined(__cplusplus) || defined(__STDC__)) */
- char *yys;
-#endif /* !(defined(__cplusplus) || defined(__STDC__)) */
-
- if ((yys = getenv("YYDEBUG")))
- {
- yyn = *yys;
- if (yyn >= '0' && yyn <= '9')
- yydebug = yyn - '0';
- }
-#endif /* YYDEBUG */
-
- yynerrs = 0;
- yyerrflag = 0;
- yychar = (-1);
-
- if (yyss == NULL && yygrowstack()) goto yyoverflow;
- yyssp = yyss;
- yyvsp = yyvs;
- *yyssp = yystate = 0;
-
-yyloop:
- if ((yyn = yydefred[yystate]) != 0) goto yyreduce;
- if (yychar < 0)
- {
- if ((yychar = yylex()) < 0) yychar = 0;
-#if YYDEBUG
- if (yydebug)
- {
- yys = 0;
- if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
- if (!yys) yys = "illegal-symbol";
- printf("%sdebug: state %d, reading %d (%s)\n",
- YYPREFIX, yystate, yychar, yys);
- }
-#endif
- }
- if ((yyn = yysindex[yystate]) && (yyn += yychar) >= 0 &&
- yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
- {
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: state %d, shifting to state %d\n",
- YYPREFIX, yystate, yytable[yyn]);
-#endif
- if (yyssp >= yysslim && yygrowstack())
- {
- goto yyoverflow;
- }
- *++yyssp = yystate = yytable[yyn];
- *++yyvsp = yylval;
- yychar = (-1);
- if (yyerrflag > 0) --yyerrflag;
- goto yyloop;
- }
- if ((yyn = yyrindex[yystate]) && (yyn += yychar) >= 0 &&
- yyn <= YYTABLESIZE && yycheck[yyn] == yychar)
- {
- yyn = yytable[yyn];
- goto yyreduce;
- }
- if (yyerrflag) goto yyinrecovery;
-#if defined(lint) || defined(__GNUC__)
- goto yynewerror;
-#endif
-yynewerror:
- yyerror("syntax error");
-#if defined(lint) || defined(__GNUC__)
- goto yyerrlab;
-#endif
-yyerrlab:
- ++yynerrs;
-yyinrecovery:
- if (yyerrflag < 3)
- {
- yyerrflag = 3;
- for (;;)
- {
- if ((yyn = yysindex[*yyssp]) && (yyn += YYERRCODE) >= 0 &&
- yyn <= YYTABLESIZE && yycheck[yyn] == YYERRCODE)
- {
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: state %d, error recovery shifting\
- to state %d\n", YYPREFIX, *yyssp, yytable[yyn]);
-#endif
- if (yyssp >= yysslim && yygrowstack())
- {
- goto yyoverflow;
- }
- *++yyssp = yystate = yytable[yyn];
- *++yyvsp = yylval;
- goto yyloop;
- }
- else
- {
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: error recovery discarding state %d\n",
- YYPREFIX, *yyssp);
-#endif
- if (yyssp <= yyss) goto yyabort;
- --yyssp;
- --yyvsp;
- }
- }
- }
- else
- {
- if (yychar == 0) goto yyabort;
-#if YYDEBUG
- if (yydebug)
- {
- yys = 0;
- if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
- if (!yys) yys = "illegal-symbol";
- printf("%sdebug: state %d, error recovery discards token %d (%s)\n",
- YYPREFIX, yystate, yychar, yys);
- }
-#endif
- yychar = (-1);
- goto yyloop;
- }
-yyreduce:
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: state %d, reducing by rule %d (%s)\n",
- YYPREFIX, yystate, yyn, yyrule[yyn]);
-#endif
- yym = yylen[yyn];
- yyval = yyvsp[1-yym];
- switch (yyn)
- {
-case 1:
-#line 277 "parse.yacc"
-{ ; }
-break;
-case 5:
-#line 286 "parse.yacc"
-{ ; }
-break;
-case 6:
-#line 288 "parse.yacc"
-{ yyerrok; }
-break;
-case 7:
-#line 289 "parse.yacc"
-{ push; }
-break;
-case 8:
-#line 289 "parse.yacc"
-{
- while (top && user_matches != TRUE)
- pop;
- }
-break;
-case 9:
-#line 294 "parse.yacc"
-{ ; }
-break;
-case 10:
-#line 296 "parse.yacc"
-{ ; }
-break;
-case 11:
-#line 298 "parse.yacc"
-{ ; }
-break;
-case 12:
-#line 300 "parse.yacc"
-{ ; }
-break;
-case 13:
-#line 302 "parse.yacc"
-{ ; }
-break;
-case 15:
-#line 308 "parse.yacc"
-{
- defaults_matches = TRUE;
- }
-break;
-case 16:
-#line 311 "parse.yacc"
-{ push; }
-break;
-case 17:
-#line 311 "parse.yacc"
-{
- defaults_matches = user_matches;
- pop;
- }
-break;
-case 18:
-#line 315 "parse.yacc"
-{ push; }
-break;
-case 19:
-#line 315 "parse.yacc"
-{
- defaults_matches = yyvsp[0].BOOLEAN == TRUE;
- pop;
- }
-break;
-case 20:
-#line 319 "parse.yacc"
-{ push; }
-break;
-case 21:
-#line 319 "parse.yacc"
-{
- defaults_matches = host_matches;
- pop;
- }
-break;
-case 24:
-#line 329 "parse.yacc"
-{
- if (defaults_matches == TRUE &&
- !set_default(yyvsp[0].string, NULL, TRUE)) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[0].string);
- }
-break;
-case 25:
-#line 337 "parse.yacc"
-{
- if (defaults_matches == TRUE &&
- !set_default(yyvsp[0].string, NULL, FALSE)) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[0].string);
- }
-break;
-case 26:
-#line 345 "parse.yacc"
-{
- if (defaults_matches == TRUE &&
- !set_default(yyvsp[-2].string, yyvsp[0].string, TRUE)) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[-2].string);
- free(yyvsp[0].string);
- }
-break;
-case 27:
-#line 354 "parse.yacc"
-{
- if (defaults_matches == TRUE &&
- !set_default(yyvsp[-2].string, yyvsp[0].string, '+')) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[-2].string);
- free(yyvsp[0].string);
- }
-break;
-case 28:
-#line 363 "parse.yacc"
-{
- if (defaults_matches == TRUE &&
- !set_default(yyvsp[-2].string, yyvsp[0].string, '-')) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[-2].string);
- free(yyvsp[0].string);
- }
-break;
-case 31:
-#line 378 "parse.yacc"
-{
- /*
- * We already did a push if necessary in
- * cmndspec so just reset some values so
- * the next 'privilege' gets a clean slate.
- */
- host_matches = UNSPEC;
- runas_matches = UNSPEC;
- no_passwd = def_authenticate ? UNSPEC : TRUE;
- no_execve = def_noexec ? TRUE : UNSPEC;
- monitor_cmnd = def_monitor ? TRUE : UNSPEC;
- }
-break;
-case 32:
-#line 392 "parse.yacc"
-{
- SETMATCH(host_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 33:
-#line 395 "parse.yacc"
-{
- SETNMATCH(host_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 34:
-#line 400 "parse.yacc"
-{
- yyval.BOOLEAN = TRUE;
- }
-break;
-case 35:
-#line 403 "parse.yacc"
-{
- if (addr_matches(yyvsp[0].string))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 36:
-#line 410 "parse.yacc"
-{
- if (netgr_matches(yyvsp[0].string, user_host, user_shost, NULL))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 37:
-#line 417 "parse.yacc"
-{
- if (hostname_matches(user_shost, user_host, yyvsp[0].string) == 0)
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 38:
-#line 424 "parse.yacc"
-{
- aliasinfo *aip = find_alias(yyvsp[0].string, HOST_ALIAS);
-
- /* could be an all-caps hostname */
- if (aip)
- yyval.BOOLEAN = aip->val;
- else if (strcasecmp(user_shost, yyvsp[0].string) == 0)
- yyval.BOOLEAN = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Host_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- yyval.BOOLEAN = NOMATCH;
- }
- free(yyvsp[0].string);
- }
-break;
-case 41:
-#line 452 "parse.yacc"
-{
- /*
- * Push the entry onto the stack if it is worth
- * saving and reset cmnd_matches for next cmnd.
- *
- * We need to save at least one entry on
- * the stack so sudoers_lookup() can tell that
- * the user was listed in sudoers. Also, we
- * need to be able to tell whether or not a
- * user was listed for this specific host.
- *
- * If keepall is set and the user matches then
- * we need to keep entries around too...
- */
- if (MATCHED(user_matches) &&
- MATCHED(host_matches) &&
- MATCHED(cmnd_matches) &&
- MATCHED(runas_matches))
- pushcp;
- else if (MATCHED(user_matches) && (top == 1 ||
- (top == 2 && MATCHED(host_matches) &&
- !MATCHED(match[0].host))))
- pushcp;
- else if (user_matches == TRUE && keepall)
- pushcp;
- cmnd_matches = UNSPEC;
- }
-break;
-case 42:
-#line 481 "parse.yacc"
-{
- SETMATCH(cmnd_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 43:
-#line 484 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("!", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_cmnd("!", NULL);
- }
- }
-break;
-case 44:
-#line 492 "parse.yacc"
-{
- SETNMATCH(cmnd_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 45:
-#line 497 "parse.yacc"
-{
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE) {
- if (runas_matches == UNSPEC) {
- cm_list[cm_list_len].runas_len = 0;
- } else {
- /* Inherit runas data. */
- cm_list[cm_list_len].runas =
- estrdup(cm_list[cm_list_len-1].runas);
- cm_list[cm_list_len].runas_len =
- cm_list[cm_list_len-1].runas_len;
- cm_list[cm_list_len].runas_size =
- cm_list[cm_list_len-1].runas_size;
- }
- }
- /*
- * If this is the first entry in a command list
- * then check against default runas user.
- */
- if (runas_matches == UNSPEC) {
- runas_matches =
- userpw_matches(def_runas_default,
- *user_runas, runas_pw);
- }
- }
-break;
-case 46:
-#line 522 "parse.yacc"
-{
- runas_matches = yyvsp[0].BOOLEAN;
- }
-break;
-case 47:
-#line 527 "parse.yacc"
-{ ; }
-break;
-case 48:
-#line 528 "parse.yacc"
-{
- /* Later entries override earlier ones. */
- if (yyvsp[0].BOOLEAN != NOMATCH)
- yyval.BOOLEAN = yyvsp[0].BOOLEAN;
- else
- yyval.BOOLEAN = yyvsp[-2].BOOLEAN;
- }
-break;
-case 49:
-#line 537 "parse.yacc"
-{ ; }
-break;
-case 50:
-#line 538 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("!", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas("!", ", ");
- }
- }
-break;
-case 51:
-#line 546 "parse.yacc"
-{
- /* Set $$ to the negation of runasuser */
- yyval.BOOLEAN = (yyvsp[0].BOOLEAN == NOMATCH ? NOMATCH : ! yyvsp[0].BOOLEAN);
- }
-break;
-case 52:
-#line 552 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries(yyvsp[0].string, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas(yyvsp[0].string, ", ");
- }
- if (userpw_matches(yyvsp[0].string, *user_runas, runas_pw))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- used_runas = TRUE;
- }
-break;
-case 53:
-#line 567 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries(yyvsp[0].string, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas(yyvsp[0].string, ", ");
- }
- if (usergr_matches(yyvsp[0].string, *user_runas, runas_pw))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- used_runas = TRUE;
- }
-break;
-case 54:
-#line 582 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries(yyvsp[0].string, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas(yyvsp[0].string, ", ");
- }
- if (netgr_matches(yyvsp[0].string, NULL, NULL, *user_runas))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- used_runas = TRUE;
- }
-break;
-case 55:
-#line 597 "parse.yacc"
-{
- aliasinfo *aip = find_alias(yyvsp[0].string, RUNAS_ALIAS);
-
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries(yyvsp[0].string, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas(yyvsp[0].string, ", ");
- }
- /* could be an all-caps username */
- if (aip)
- yyval.BOOLEAN = aip->val;
- else if (strcmp(yyvsp[0].string, *user_runas) == 0)
- yyval.BOOLEAN = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Runas_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- yyval.BOOLEAN = NOMATCH;
- }
- free(yyvsp[0].string);
- used_runas = TRUE;
- }
-break;
-case 56:
-#line 627 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("ALL", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE)
- append_runas("ALL", ", ");
- }
- yyval.BOOLEAN = TRUE;
- }
-break;
-case 57:
-#line 639 "parse.yacc"
-{
- /* Inherit tags. */
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE) {
- if (no_passwd == TRUE)
- cm_list[cm_list_len].nopasswd = TRUE;
- else
- cm_list[cm_list_len].nopasswd = FALSE;
- if (no_execve == TRUE)
- cm_list[cm_list_len].noexecve = TRUE;
- else
- cm_list[cm_list_len].noexecve = FALSE;
- if (monitor_cmnd == TRUE)
- cm_list[cm_list_len].monitor = TRUE;
- else
- cm_list[cm_list_len].monitor = FALSE;
- }
- }
-break;
-case 58:
-#line 657 "parse.yacc"
-{
- no_passwd = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].nopasswd = TRUE;
- }
-break;
-case 59:
-#line 663 "parse.yacc"
-{
- no_passwd = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].nopasswd = FALSE;
- }
-break;
-case 60:
-#line 669 "parse.yacc"
-{
- no_execve = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].noexecve = TRUE;
- }
-break;
-case 61:
-#line 675 "parse.yacc"
-{
- no_execve = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].noexecve = FALSE;
- }
-break;
-case 62:
-#line 681 "parse.yacc"
-{
- monitor_cmnd = TRUE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].monitor = TRUE;
- }
-break;
-case 63:
-#line 687 "parse.yacc"
-{
- monitor_cmnd = FALSE;
- if (printmatches == TRUE && host_matches == TRUE &&
- user_matches == TRUE)
- cm_list[cm_list_len].monitor = FALSE;
- }
-break;
-case 64:
-#line 695 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries("ALL", ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd("ALL", NULL);
- expand_match_list();
- }
- }
-
- yyval.BOOLEAN = TRUE;
-
- if (safe_cmnd)
- free(safe_cmnd);
- safe_cmnd = estrdup(user_cmnd);
- }
-break;
-case 65:
-#line 712 "parse.yacc"
-{
- aliasinfo *aip;
-
- if (printmatches == TRUE) {
- if (in_alias == TRUE)
- append_entries(yyvsp[0].string, ", ");
- else if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd(yyvsp[0].string, NULL);
- expand_match_list();
- }
- }
-
- if ((aip = find_alias(yyvsp[0].string, CMND_ALIAS)))
- yyval.BOOLEAN = aip->val;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared Cmnd_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- yyval.BOOLEAN = NOMATCH;
- }
- free(yyvsp[0].string);
- }
-break;
-case 66:
-#line 741 "parse.yacc"
-{
- if (printmatches == TRUE) {
- if (in_alias == TRUE) {
- append_entries(yyvsp[0].command.cmnd, ", ");
- if (yyvsp[0].command.args)
- append_entries(yyvsp[0].command.args, " ");
- }
- if (host_matches == TRUE &&
- user_matches == TRUE) {
- append_cmnd(yyvsp[0].command.cmnd, NULL);
- if (yyvsp[0].command.args)
- append_cmnd(yyvsp[0].command.args, " ");
- expand_match_list();
- }
- }
-
- if (command_matches(yyvsp[0].command.cmnd, yyvsp[0].command.args))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
-
- free(yyvsp[0].command.cmnd);
- if (yyvsp[0].command.args)
- free(yyvsp[0].command.args);
- }
-break;
-case 69:
-#line 772 "parse.yacc"
-{ push; }
-break;
-case 70:
-#line 772 "parse.yacc"
-{
- if ((MATCHED(host_matches) || pedantic) &&
- !add_alias(yyvsp[-3].string, HOST_ALIAS, host_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- }
-break;
-case 75:
-#line 790 "parse.yacc"
-{
- push;
- if (printmatches == TRUE) {
- in_alias = TRUE;
- /* Allocate space for ga_list if necessary. */
- expand_ga_list();
- ga_list[ga_list_len-1].type = CMND_ALIAS;
- ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string);
- }
- }
-break;
-case 76:
-#line 799 "parse.yacc"
-{
- if ((MATCHED(cmnd_matches) || pedantic) &&
- !add_alias(yyvsp[-3].string, CMND_ALIAS, cmnd_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- free(yyvsp[-3].string);
-
- if (printmatches == TRUE)
- in_alias = FALSE;
- }
-break;
-case 77:
-#line 813 "parse.yacc"
-{ ; }
-break;
-case 81:
-#line 821 "parse.yacc"
-{
- if (printmatches == TRUE) {
- in_alias = TRUE;
- /* Allocate space for ga_list if necessary. */
- expand_ga_list();
- ga_list[ga_list_len-1].type = RUNAS_ALIAS;
- ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string);
- }
- }
-break;
-case 82:
-#line 829 "parse.yacc"
-{
- if ((yyvsp[0].BOOLEAN != NOMATCH || pedantic) &&
- !add_alias(yyvsp[-3].string, RUNAS_ALIAS, yyvsp[0].BOOLEAN)) {
- yyerror(NULL);
- YYERROR;
- }
- free(yyvsp[-3].string);
-
- if (printmatches == TRUE)
- in_alias = FALSE;
- }
-break;
-case 85:
-#line 846 "parse.yacc"
-{ push; }
-break;
-case 86:
-#line 846 "parse.yacc"
-{
- if ((MATCHED(user_matches) || pedantic) &&
- !add_alias(yyvsp[-3].string, USER_ALIAS, user_matches)) {
- yyerror(NULL);
- YYERROR;
- }
- pop;
- free(yyvsp[-3].string);
- }
-break;
-case 89:
-#line 861 "parse.yacc"
-{
- SETMATCH(user_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 90:
-#line 864 "parse.yacc"
-{
- SETNMATCH(user_matches, yyvsp[0].BOOLEAN);
- }
-break;
-case 91:
-#line 869 "parse.yacc"
-{
- if (userpw_matches(yyvsp[0].string, user_name, sudo_user.pw))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 92:
-#line 876 "parse.yacc"
-{
- if (usergr_matches(yyvsp[0].string, user_name, sudo_user.pw))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 93:
-#line 883 "parse.yacc"
-{
- if (netgr_matches(yyvsp[0].string, NULL, NULL, user_name))
- yyval.BOOLEAN = TRUE;
- else
- yyval.BOOLEAN = NOMATCH;
- free(yyvsp[0].string);
- }
-break;
-case 94:
-#line 890 "parse.yacc"
-{
- aliasinfo *aip = find_alias(yyvsp[0].string, USER_ALIAS);
-
- /* could be an all-caps username */
- if (aip)
- yyval.BOOLEAN = aip->val;
- else if (strcmp(yyvsp[0].string, user_name) == 0)
- yyval.BOOLEAN = TRUE;
- else {
- if (pedantic) {
- (void) fprintf(stderr,
- "%s: undeclared User_Alias `%s' referenced near line %d\n",
- (pedantic == 1) ? "Warning" : "Error", yyvsp[0].string, sudolineno);
- if (pedantic > 1) {
- yyerror(NULL);
- YYERROR;
- }
- }
- yyval.BOOLEAN = NOMATCH;
- }
- free(yyvsp[0].string);
- }
-break;
-case 95:
-#line 912 "parse.yacc"
-{
- yyval.BOOLEAN = TRUE;
- }
-break;
-#line 1961 "sudo.tab.c"
- }
- yyssp -= yym;
- yystate = *yyssp;
- yyvsp -= yym;
- yym = yylhs[yyn];
- if (yystate == 0 && yym == 0)
- {
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: after reduction, shifting from state 0 to\
- state %d\n", YYPREFIX, YYFINAL);
-#endif
- yystate = YYFINAL;
- *++yyssp = YYFINAL;
- *++yyvsp = yyval;
- if (yychar < 0)
- {
- if ((yychar = yylex()) < 0) yychar = 0;
-#if YYDEBUG
- if (yydebug)
- {
- yys = 0;
- if (yychar <= YYMAXTOKEN) yys = yyname[yychar];
- if (!yys) yys = "illegal-symbol";
- printf("%sdebug: state %d, reading %d (%s)\n",
- YYPREFIX, YYFINAL, yychar, yys);
- }
-#endif
- }
- if (yychar == 0) goto yyaccept;
- goto yyloop;
- }
- if ((yyn = yygindex[yym]) && (yyn += yystate) >= 0 &&
- yyn <= YYTABLESIZE && yycheck[yyn] == yystate)
- yystate = yytable[yyn];
- else
- yystate = yydgoto[yym];
-#if YYDEBUG
- if (yydebug)
- printf("%sdebug: after reduction, shifting from state %d \
-to state %d\n", YYPREFIX, *yyssp, yystate);
-#endif
- if (yyssp >= yysslim && yygrowstack())
- {
- goto yyoverflow;
- }
- *++yyssp = yystate;
- *++yyvsp = yyval;
- goto yyloop;
-yyoverflow:
- yyerror("yacc stack overflow");
-yyabort:
- if (yyss)
- free(yyss);
- if (yyvs)
- free(yyvs);
- yyss = yyssp = NULL;
- yyvs = yyvsp = NULL;
- yystacksize = 0;
- return (1);
-yyaccept:
- if (yyss)
- free(yyss);
- if (yyvs)
- free(yyvs);
- yyss = yyssp = NULL;
- yyvs = yyvsp = NULL;
- yystacksize = 0;
- return (0);
-}