From dffd0a4d6c7d57321d9af4e86d78d48d323942d1 Mon Sep 17 00:00:00 2001 From: Martin Schulze Date: Thu, 22 Sep 2005 23:32:16 +0200 Subject: [PATCH] Imported Debian patch 1.6.6-1.4 --- auth/pam.c.orig | 262 +++++ auth/pam.c.rej | 22 + debian/changelog | 10 +- env.c | 2 + parse.yacc | 4 + sudo.c | 10 +- sudo.tab.c | 2546 ++++++++++++++++++---------------------------- sudo.tab.h | 53 +- 8 files changed, 1303 insertions(+), 1606 deletions(-) create mode 100644 auth/pam.c.orig create mode 100644 auth/pam.c.rej diff --git a/auth/pam.c.orig b/auth/pam.c.orig new file mode 100644 index 0000000..554a0e1 --- /dev/null +++ b/auth/pam.c.orig @@ -0,0 +1,262 @@ +/* + * Copyright (c) 1999-2001 Todd C. Miller + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. The name of the author may not be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * 4. Products derived from this software may not be called "Sudo" nor + * may "Sudo" appear in their names without specific prior written + * permission from the author. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL + * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include +#include +#include +#ifdef STDC_HEADERS +# include +# include +#else +# ifdef HAVE_STDLIB_H +# include +# endif +#endif /* STDC_HEADERS */ +#ifdef HAVE_STRING_H +# if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS) +# include +# endif +# include +#else +# ifdef HAVE_STRINGS_H +# include +# endif +#endif /* HAVE_STRING_H */ +#ifdef HAVE_UNISTD_H +# include +#endif /* HAVE_UNISTD_H */ +#include + +#include + +#include "sudo.h" +#include "sudo_auth.h" + +#ifndef lint +static const char rcsid[] = "$Sudo: pam.c,v 1.29 2002/01/22 16:43:23 millert Exp $"; +#endif /* lint */ + +static int sudo_conv __P((int, PAM_CONST struct pam_message **, + struct pam_response **, VOID *)); +static char *def_prompt; + +#ifndef PAM_DATA_SILENT +#define PAM_DATA_SILENT 0 +#endif + +int +pam_init(pw, promptp, auth) + struct passwd *pw; + char **promptp; + sudo_auth *auth; +{ + static struct pam_conv pam_conv; + pam_handle_t *pamh; + + /* Initial PAM setup */ + pam_conv.conv = sudo_conv; + if (pam_start("sudo", pw->pw_name, &pam_conv, &pamh) != PAM_SUCCESS) { + log_error(USE_ERRNO|NO_EXIT|NO_MAIL, + "unable to initialize PAM"); + return(AUTH_FATAL); + } + if (strcmp(user_tty, "unknown")) + (void) pam_set_item(pamh, PAM_TTY, user_tty); + + auth->data = (VOID *) pamh; + return(AUTH_SUCCESS); +} + +int +pam_verify(pw, prompt, auth) + struct passwd *pw; + char *prompt; + sudo_auth *auth; +{ + int error; + const char *s; + pam_handle_t *pamh = (pam_handle_t *) auth->data; + + def_prompt = prompt; /* for sudo_conv */ + + /* PAM_SILENT prevents the authentication service from generating output. */ + error = pam_authenticate(pamh, PAM_SILENT); + switch (error) { + case PAM_SUCCESS: + return(AUTH_SUCCESS); + case PAM_AUTH_ERR: + case PAM_MAXTRIES: + return(AUTH_FAILURE); + default: + if ((s = pam_strerror(pamh, error))) + log_error(NO_EXIT|NO_MAIL, "pam_authenticate: %s", s); + return(AUTH_FATAL); + } +} + +int +pam_cleanup(pw, auth) + struct passwd *pw; + sudo_auth *auth; +{ + pam_handle_t *pamh = (pam_handle_t *) auth->data; + int status = PAM_DATA_SILENT; + + /* Convert AUTH_FOO -> PAM_FOO as best we can. */ + /* XXX - store real value somewhere in auth->data and use it */ + switch (auth->status) { + case AUTH_SUCCESS: + status |= PAM_SUCCESS; + break; + case AUTH_FAILURE: + status |= PAM_AUTH_ERR; + break; + case AUTH_FATAL: + default: + status |= PAM_ABORT; + break; + } + + if (pam_end(pamh, status) == PAM_SUCCESS) + return(AUTH_SUCCESS); + else + return(AUTH_FAILURE); +} + +int +pam_prep_user(pw) + struct passwd *pw; +{ + struct pam_conv pam_conv; + pam_handle_t *pamh; + + /* We need to setup a new PAM session for the user we are changing *to*. */ + pam_conv.conv = sudo_conv; + if (pam_start("sudo", pw->pw_name, &pam_conv, &pamh) != PAM_SUCCESS) { + log_error(USE_ERRNO|NO_EXIT|NO_MAIL, + "unable to initialize PAM"); + return(AUTH_FATAL); + } + (void) pam_set_item(pamh, PAM_RUSER, user_name); + if (strcmp(user_tty, "unknown")) + (void) pam_set_item(pamh, PAM_TTY, user_tty); + + /* + * Set credentials (may include resource limits, device ownership, etc). + * We don't check the return value here because in Linux-PAM 0.75 + * it returns the last saved return code, not the return code + * for the setcred module. Because we haven't called pam_authenticate(), + * this is not set and so pam_setcred() returns PAM_PERM_DENIED. + * We can't call pam_acct_mgmt() with Linux-PAM for a similar reason. + */ + (void) pam_setcred(pamh, PAM_ESTABLISH_CRED); + + if (pam_end(pamh, PAM_SUCCESS) == PAM_SUCCESS) + return(PAM_SUCCESS); + else + return(AUTH_FAILURE); +} + +/* + * ``Conversation function'' for PAM. + * XXX - does not handle PAM_BINARY_PROMPT + */ +static int +sudo_conv(num_msg, msg, response, appdata_ptr) + int num_msg; + PAM_CONST struct pam_message **msg; + struct pam_response **response; + VOID *appdata_ptr; +{ + struct pam_response *pr; + PAM_CONST struct pam_message *pm; + const char *p = def_prompt; + char *pass; + int n; + extern int nil_pw; + + if ((*response = malloc(num_msg * sizeof(struct pam_response))) == NULL) + return(PAM_CONV_ERR); + (void) memset(*response, 0, num_msg * sizeof(struct pam_response)); + + for (pr = *response, pm = *msg, n = num_msg; n--; pr++, pm++) { + switch (pm->msg_style) { + case PAM_PROMPT_ECHO_ON: + tgetpass_flags |= TGP_ECHO; + case PAM_PROMPT_ECHO_OFF: + /* Only override PAM prompt if it matches /^Password: ?/ */ + if (strncmp(pm->msg, "Password:", 9) || (pm->msg[9] != '\0' + && (pm->msg[9] != ' ' || pm->msg[10] != '\0'))) + p = pm->msg; + /* Read the password. */ + pr->resp = estrdup((char *) tgetpass(p, + def_ival(I_PASSWD_TIMEOUT) * 60, tgetpass_flags)); + if (pr->resp == NULL) + pr->resp = strdup(""); + if (*pr->resp == '\0') + nil_pw = 1; /* empty password */ + else + memset(pass, 0, strlen(pass)); + break; + case PAM_TEXT_INFO: + if (pm->msg) + (void) puts(pm->msg); + break; + case PAM_ERROR_MSG: + if (pm->msg) { + (void) fputs(pm->msg, stderr); + (void) fputc('\n', stderr); + } + break; + default: + /* Zero and free allocated memory and return an error. */ + for (pr = *response, n = num_msg; n--; pr++) { + if (pr->resp != NULL) { + (void) memset(pr->resp, 0, strlen(pr->resp)); + free(pr->resp); + pr->resp = NULL; + } + } + (void) memset(*response, 0, + num_msg * sizeof(struct pam_response)); + free(*response); + *response = NULL; + return(PAM_CONV_ERR); + } + } + + return(PAM_SUCCESS); +} diff --git a/auth/pam.c.rej b/auth/pam.c.rej new file mode 100644 index 0000000..86273af --- /dev/null +++ b/auth/pam.c.rej @@ -0,0 +1,22 @@ +*************** +*** 222,231 **** + && (pm->msg[9] != ' ' || pm->msg[10] != '\0'))) + p = pm->msg; + /* Read the password. */ +- pr->resp = estrdup((char *) tgetpass(p, +- def_ival(I_PASSWD_TIMEOUT) * 60, tgetpass_flags)); +- if (pr->resp == NULL) +- pr->resp = strdup(""); + if (*pr->resp == '\0') + nil_pw = 1; /* empty password */ + else +--- 222,230 ---- + && (pm->msg[9] != ' ' || pm->msg[10] != '\0'))) + p = pm->msg; + /* Read the password. */ ++ pass = tgetpass(p, def_ival(I_PASSWD_TIMEOUT) * 60, ++ tgetpass_flags); ++ pr->resp = estrdup(pass ? pass : ""); + if (*pr->resp == '\0') + nil_pw = 1; /* empty password */ + else diff --git a/debian/changelog b/debian/changelog index b69108e..06a7103 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,10 +1,10 @@ -sudo (1.6.6-1.3woody1) oldstable-security; urgency=high +sudo (1.6.6-1.4) oldstable-security; urgency=high - * Security upload - * Fix race condition in pathname validation [CAN-2005-1993] - (Closes: #315115) + * Non-maintainer upload by the Security Team + * Clean SHELLOPTS and PS4 from the environment before executing programs + with sudo permissions [env.c, CAN-2005-2959] - -- Jeroen van Wolffelaar Wed, 29 Jun 2005 03:56:11 +0200 + -- Martin Schulze Thu, 22 Sep 2005 23:32:16 +0200 sudo (1.6.6-1.3) stable-security; urgency=high diff --git a/env.c b/env.c index b4feef1..5a53b5d 100644 --- a/env.c +++ b/env.c @@ -96,6 +96,8 @@ static char *format_env __P((char *, char *)); char *initial_badenv_table[] = { "IFS", "CDPATH", + "SHELLOPTS", + "PS4", "LOCALDOMAIN", "RES_OPTIONS", "HOSTALIASES", diff --git a/parse.yacc b/parse.yacc index 04794ae..7a6fb4e 100644 --- a/parse.yacc +++ b/parse.yacc @@ -638,6 +638,10 @@ cmnd : ALL { } $$ = TRUE; + + if (safe_cmnd) + free(safe_cmnd); + safe_cmnd = estrdup(user_cmnd); } | ALIAS { aliasinfo *aip; diff --git a/sudo.c b/sudo.c index 4052ad4..7c6f532 100644 --- a/sudo.c +++ b/sudo.c @@ -286,8 +286,6 @@ main(argc, argv, envp) if (runas_pw == NULL) log_error(NO_MAIL|MSG_ONLY, "no passwd entry for %s!", *user_runas); } - if (safe_cmnd == NULL) - safe_cmnd = user_cmnd; /* This goes after the sudoers parse since we honor sudoers options. */ if (sudo_mode == MODE_KILL || sudo_mode == MODE_INVALIDATE) { @@ -356,6 +354,14 @@ main(argc, argv, envp) exit(0); } + /* This *must* have been set if we got a match but... */ + if (safe_cmnd == NULL) { + log_error(MSG_ONLY, + "internal error, safe_cmnd never got set for %s; %s", + user_cmnd, + "please report this error at http://courtesan.com/sudo/bugs/"); + } + /* Reset signal handlers before we exec. */ sigemptyset(&sa.sa_mask); sa.sa_flags = SA_RESTART; diff --git a/sudo.tab.c b/sudo.tab.c index ca77a2b..db81c13 100644 --- a/sudo.tab.c +++ b/sudo.tab.c @@ -1,31 +1,22 @@ -/* A Bison parser, made from parse.yacc - by GNU bison 1.35. */ - -#define YYBISON 1 /* Identify Bison output. */ - -# 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 RUNAS 267 -# define NOPASSWD 268 -# define PASSWD 269 -# define ALL 270 -# define COMMENT 271 -# define HOSTALIAS 272 -# define CMNDALIAS 273 -# define USERALIAS 274 -# define RUNASALIAS 275 -# define ERROR 276 - -#line 1 "parse.yacc" - +#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.18 2001/11/19 19:02:18 mpech Exp $"; +#endif +#include +#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-2001 Todd C. Miller * All rights reserved. @@ -112,7 +103,7 @@ #endif /* HAVE_LSEARCH */ #ifndef lint -static const char rcsid[] = "$Sudo: parse.yacc,v 1.180 2002/03/16 00:44:47 millert Exp $"; +static const char rcsid[] = "$Sudo: sudo.tab.c,v 1.58 2002/03/16 00:45:48 millert Exp $"; #endif /* lint */ /* @@ -236,1039 +227,984 @@ yyerror(s) } parse_error = TRUE; } - #line 214 "parse.yacc" -#ifndef YYSTYPE typedef union { char *string; int BOOLEAN; struct sudo_command command; int tok; -} yystype; -# define YYSTYPE yystype -# define YYSTYPE_IS_TRIVIAL 1 -#endif -#ifndef YYDEBUG -# define YYDEBUG 0 -#endif - - - -#define YYFINAL 129 -#define YYFLAG -32768 -#define YYNTBASE 29 - -/* YYTRANSLATE(YYLEX) -- Bison token number corresponding to YYLEX. */ -#define YYTRANSLATE(x) ((unsigned)(x) <= 276 ? yytranslate[x] : 70) - -/* YYTRANSLATE[YYLEX] -- Bison token number corresponding to YYLEX. */ -static const char yytranslate[] = -{ - 0, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 25, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 26, 24, 27, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 22, 2, - 2, 23, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, - 2, 2, 2, 2, 2, 2, 1, 3, 4, 5, - 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 28 -}; - -#if YYDEBUG -static const short yyprhs[] = -{ - 0, 0, 2, 5, 7, 10, 11, 15, 18, 21, - 24, 27, 29, 32, 34, 35, 39, 40, 44, 46, - 50, 52, 55, 59, 63, 67, 69, 73, 77, 79, - 82, 84, 86, 88, 90, 92, 94, 98, 102, 104, - 105, 109, 110, 113, 115, 119, 121, 122, 126, 128, - 130, 132, 134, 136, 137, 139, 141, 143, 145, 147, - 149, 153, 154, 159, 161, 165, 167, 171, 172, 177, - 179, 183, 185, 189, 190, 195, 197, 201, 202, 207, - 209, 213, 215, 218, 220, 222, 224, 226 -}; -static const short yyrhs[] = -{ - 30, 0, 29, 30, 0, 17, 0, 1, 17, 0, - 0, 31, 67, 38, 0, 20, 64, 0, 18, 53, - 0, 19, 57, 0, 21, 61, 0, 32, 0, 33, - 36, 0, 10, 0, 0, 12, 34, 67, 0, 0, - 11, 35, 56, 0, 37, 0, 37, 24, 36, 0, - 5, 0, 25, 5, 0, 5, 23, 9, 0, 5, - 26, 9, 0, 5, 27, 9, 0, 39, 0, 38, - 22, 39, 0, 56, 23, 42, 0, 41, 0, 25, - 41, 0, 16, 0, 6, 0, 7, 0, 9, 0, - 4, 0, 43, 0, 42, 24, 43, 0, 46, 51, - 44, 0, 52, 0, 0, 25, 45, 52, 0, 0, - 13, 47, 0, 48, 0, 47, 24, 48, 0, 50, - 0, 0, 25, 49, 50, 0, 9, 0, 8, 0, - 7, 0, 4, 0, 16, 0, 0, 14, 0, 15, - 0, 16, 0, 4, 0, 3, 0, 54, 0, 53, - 22, 54, 0, 0, 4, 55, 23, 56, 0, 40, - 0, 56, 24, 40, 0, 58, 0, 57, 22, 58, - 0, 0, 4, 59, 23, 60, 0, 44, 0, 60, - 24, 44, 0, 62, 0, 61, 22, 62, 0, 0, - 4, 63, 23, 47, 0, 65, 0, 64, 22, 65, - 0, 0, 4, 66, 23, 67, 0, 68, 0, 67, - 24, 68, 0, 69, 0, 25, 69, 0, 9, 0, - 8, 0, 7, 0, 4, 0, 16, 0 -}; - -#endif - -#if YYDEBUG -/* YYRLINE[YYN] -- source line where rule number YYN was defined. */ -static const short yyrline[] = -{ - 0, 259, 260, 263, 265, 267, 267, 271, 273, 275, - 277, 279, 283, 285, 288, 288, 292, 292, 298, 299, - 301, 309, 317, 326, 335, 345, 346, 349, 364, 368, - 373, 376, 383, 390, 397, 421, 422, 425, 452, 456, - 456, 470, 493, 498, 499, 508, 509, 509, 522, 536, - 550, 564, 593, 605, 615, 621, 629, 642, 671, 699, - 700, 703, 703, 711, 712, 715, 716, 719, 719, 740, - 741, 744, 745, 748, 748, 767, 768, 771, 771, 780, - 781, 784, 788, 793, 800, 807, 814, 834 -}; -#endif - - -#if (YYDEBUG) || defined YYERROR_VERBOSE - -/* YYTNAME[TOKEN_NUM] -- String name of the token TOKEN_NUM. */ -static const char *const yytname[] = -{ - "$", "error", "$undefined.", "COMMAND", "ALIAS", "DEFVAR", "NTWKADDR", - "NETGROUP", "USERGROUP", "WORD", "DEFAULTS", "DEFAULTS_HOST", - "DEFAULTS_USER", "RUNAS", "NOPASSWD", "PASSWD", "ALL", "COMMENT", - "HOSTALIAS", "CMNDALIAS", "USERALIAS", "RUNASALIAS", "':'", "'='", - "','", "'!'", "'+'", "'-'", "ERROR", "file", "entry", "@1", - "defaults_line", "defaults_type", "@2", "@3", "defaults_list", - "defaults_entry", "privileges", "privilege", "ophost", "host", - "cmndspeclist", "cmndspec", "opcmnd", "@4", "runasspec", "runaslist", - "oprunasuser", "@5", "runasuser", "nopasswd", "cmnd", "hostaliases", - "hostalias", "@6", "hostlist", "cmndaliases", "cmndalias", "@7", - "cmndlist", "runasaliases", "runasalias", "@8", "useraliases", - "useralias", "@9", "userlist", "opuser", "user", 0 -}; -#endif - -/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */ -static const short yyr1[] = -{ - 0, 29, 29, 30, 30, 31, 30, 30, 30, 30, - 30, 30, 32, 33, 34, 33, 35, 33, 36, 36, - 37, 37, 37, 37, 37, 38, 38, 39, 40, 40, - 41, 41, 41, 41, 41, 42, 42, 43, 44, 45, - 44, 46, 46, 47, 47, 48, 49, 48, 50, 50, - 50, 50, 50, 51, 51, 51, 52, 52, 52, 53, - 53, 55, 54, 56, 56, 57, 57, 59, 58, 60, - 60, 61, 61, 63, 62, 64, 64, 66, 65, 67, - 67, 68, 68, 69, 69, 69, 69, 69 +} YYSTYPE; +#line 238 "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 RUNAS 267 +#define NOPASSWD 268 +#define PASSWD 269 +#define ALL 270 +#define COMMENT 271 +#define HOSTALIAS 272 +#define CMNDALIAS 273 +#define USERALIAS 274 +#define RUNASALIAS 275 +#define ERROR 276 +#define YYERRCODE 256 +short yylhs[] = { -1, + 0, 0, 7, 7, 9, 7, 7, 7, 7, 7, + 7, 15, 16, 18, 16, 20, 16, 17, 17, 21, + 21, 21, 21, 21, 10, 10, 22, 24, 24, 2, + 2, 2, 2, 2, 23, 23, 25, 28, 29, 28, + 26, 26, 5, 5, 4, 30, 4, 3, 3, 3, + 3, 3, 27, 27, 27, 1, 1, 1, 12, 12, + 32, 31, 19, 19, 13, 13, 34, 33, 35, 35, + 14, 14, 37, 36, 11, 11, 39, 38, 8, 8, + 40, 40, 6, 6, 6, 6, 6, }; - -/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */ -static const short yyr2[] = -{ - 0, 1, 2, 1, 2, 0, 3, 2, 2, 2, - 2, 1, 2, 1, 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, 1, 1, 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 +short yylen[] = { 2, + 1, 2, 1, 2, 0, 3, 2, 2, 2, 2, + 1, 2, 1, 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, 1, 1, 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, }; - -/* YYDEFACT[S] -- default rule to reduce with in state S when YYTABLE - doesn't specify something else to do. Zero means the default is an - error. */ -static const short yydefact[] = -{ - 0, 0, 13, 16, 14, 3, 0, 0, 0, 0, - 0, 1, 0, 11, 0, 4, 0, 0, 61, 8, - 59, 67, 9, 65, 77, 7, 75, 73, 10, 71, - 2, 86, 85, 84, 83, 87, 0, 0, 79, 81, - 20, 0, 12, 18, 34, 31, 32, 33, 30, 0, - 63, 28, 17, 15, 0, 0, 0, 0, 0, 0, - 0, 0, 82, 0, 6, 25, 0, 0, 0, 0, - 21, 0, 29, 0, 0, 60, 0, 66, 0, 76, - 0, 72, 80, 0, 41, 22, 23, 24, 19, 64, - 62, 58, 57, 56, 39, 69, 38, 68, 78, 51, - 50, 49, 48, 52, 46, 74, 43, 45, 26, 0, - 27, 35, 53, 0, 0, 0, 0, 42, 41, 54, - 55, 0, 40, 70, 47, 44, 36, 37, 0, 0 +short yydefred[] = { 0, + 0, 13, 16, 14, 3, 0, 0, 0, 0, 0, + 1, 0, 11, 0, 4, 0, 0, 61, 0, 59, + 67, 0, 65, 77, 0, 75, 73, 0, 71, 2, + 86, 85, 84, 83, 87, 0, 81, 0, 79, 0, + 0, 12, 0, 34, 31, 32, 33, 30, 0, 28, + 0, 63, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 82, 0, 0, 0, 25, 0, 0, 0, 21, + 0, 29, 0, 0, 60, 0, 66, 0, 76, 0, + 72, 80, 0, 0, 22, 23, 24, 19, 64, 0, + 58, 57, 56, 39, 38, 69, 0, 0, 51, 50, + 49, 48, 52, 46, 45, 43, 0, 26, 0, 0, + 35, 0, 0, 0, 0, 0, 0, 0, 54, 55, + 0, 40, 70, 47, 44, 36, 37, }; - -static const short yydefgoto[] = -{ - 10, 11, 12, 13, 14, 17, 16, 42, 43, 64, - 65, 50, 51, 110, 111, 95, 113, 112, 105, 106, - 115, 107, 121, 96, 19, 20, 54, 66, 22, 23, - 56, 97, 28, 29, 60, 25, 26, 58, 37, 38, - 39 +short yydgoto[] = { 10, + 95, 50, 105, 106, 107, 37, 11, 38, 12, 64, + 25, 19, 22, 28, 13, 14, 42, 17, 65, 16, + 43, 66, 110, 52, 111, 112, 121, 96, 113, 115, + 20, 54, 23, 56, 97, 29, 60, 26, 58, 39, }; - -static const short yypact[] = -{ - 24, -10,-32768,-32768,-32768,-32768, 12, 20, 35, 50, - 2,-32768, 48,-32768, 33,-32768, 68, 48,-32768, 15, - -32768,-32768, 40,-32768,-32768, 41,-32768,-32768, 45,-32768, - -32768,-32768,-32768,-32768,-32768,-32768, 78, 44,-32768,-32768, - 83, 65,-32768, 47,-32768,-32768,-32768,-32768,-32768, 92, - -32768,-32768, 59, 66, 69, 12, 79, 20, 84, 35, - 88, 50,-32768, 48, 67,-32768, 6, 82, 86, 104, - -32768, 33,-32768, 68, 68,-32768, 1,-32768, 48,-32768, - 72,-32768,-32768, 68, 101,-32768,-32768,-32768,-32768,-32768, - 59,-32768,-32768,-32768,-32768,-32768,-32768, 91, 66,-32768, - -32768,-32768,-32768,-32768,-32768, 93,-32768,-32768,-32768, 72, - 94,-32768, 32, 62, 1, 96, 72, 93, 101,-32768, - -32768, 1,-32768,-32768,-32768,-32768,-32768,-32768, 116,-32768 +short yysindex[] = { -236, + -264, 0, 0, 0, 0, -249, -243, -231, -227, -236, + 0, -23, 0, -30, 0, -17, -23, 0, -36, 0, + 0, -26, 0, 0, -14, 0, 0, -7, 0, 0, + 0, 0, 0, 0, 0, -215, 0, -33, 0, -3, + -226, 0, 5, 0, 0, 0, 0, 0, -194, 0, + 6, 0, 8, -5, -249, -4, -243, -2, -231, -1, + -227, 0, -23, 7, -38, 0, -210, -193, -188, 0, + -30, 0, -17, -17, 0, -25, 0, -23, 0, 245, + 0, 0, -17, -189, 0, 0, 0, 0, 0, 6, + 0, 0, 0, 0, 0, 0, 33, 8, 0, 0, + 0, 0, 0, 0, 0, 0, 38, 0, 245, 39, + 0, -251, -244, -25, -190, 245, 38, -189, 0, 0, + -25, 0, 0, 0, 0, 0, 0, }; - -static const short yypgoto[] = -{ - -32768, 109,-32768,-32768,-32768,-32768,-32768, 49,-32768,-32768, - 38, 51, 73,-32768, 5, -106,-32768,-32768, 16, 10, - -32768, 13,-32768, 14,-32768, 74,-32768, -15,-32768, 75, - -32768,-32768,-32768, 70,-32768,-32768, 71,-32768, -17, 76, - 97 +short yyrindex[] = { 255, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 255, + 0, 0, 0, 0, 0, 0, 0, 0, 121, 0, + 0, 141, 0, 0, 161, 0, 0, 181, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, + 0, 0, 201, 0, 0, 0, 0, 0, 0, 0, + -28, 0, -8, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 221, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 265, 0, 0, 0, 0, 0, 21, + 0, 0, 0, 0, 0, 0, 41, 61, 0, 0, + 0, 0, 0, 0, 0, 0, 81, 0, 0, 101, + 0, -9, 0, 0, 0, 0, 285, 265, 0, 0, + 0, 0, 0, 0, 0, 0, 0, }; - - -#define YYLAST 139 - - -static const short yytable[] = -{ - 53, 52, 128, 1, 91, 92, -5, 15, 123, -5, - -5, -5, 2, 3, 4, 127, 18, 93, -5, 5, - 6, 7, 8, 9, 21, 1, 94, -5, -5, 84, - 73, -5, -5, -5, 2, 3, 4, 55, 40, 24, - -5, 5, 6, 7, 8, 9, 119, 120, 44, -5, - 45, 46, 31, 47, 27, 32, 33, 34, 41, 90, - 48, 98, 57, 59, 35, 91, 92, 61, 63, 49, - 70, 71, 44, 36, 45, 46, 99, 47, 93, 100, - 101, 102, 31, 73, 48, 32, 33, 34, 103, 83, - 63, 85, 74, 49, 35, 86, 44, 104, 45, 46, - 99, 47, 76, 100, 101, 102, 67, 78, 48, 68, - 69, 80, 103, 87, 109, 114, 129, 116, 118, 30, - 88, 108, 72, 126, 89, 117, 125, 122, 124, 75, - 79, 81, 77, 62, 0, 0, 0, 0, 0, 82 +short yygindex[] = { 0, + -29, 36, -27, -24, -22, 50, 79, -15, 0, 0, + 0, 0, 0, 0, 0, 0, 19, 0, -12, 0, + 0, 10, 0, 18, -21, 0, 0, -102, 0, 0, + 40, 0, 43, 0, 0, 35, 0, 44, 0, 42, }; - -static const short yycheck[] = -{ - 17, 16, 0, 1, 3, 4, 4, 17, 114, 7, - 8, 9, 10, 11, 12, 121, 4, 16, 16, 17, - 18, 19, 20, 21, 4, 1, 25, 25, 4, 23, - 24, 7, 8, 9, 10, 11, 12, 22, 5, 4, - 16, 17, 18, 19, 20, 21, 14, 15, 4, 25, - 6, 7, 4, 9, 4, 7, 8, 9, 25, 74, - 16, 78, 22, 22, 16, 3, 4, 22, 24, 25, - 5, 24, 4, 25, 6, 7, 4, 9, 16, 7, - 8, 9, 4, 24, 16, 7, 8, 9, 16, 22, - 24, 9, 23, 25, 16, 9, 4, 25, 6, 7, - 4, 9, 23, 7, 8, 9, 23, 23, 16, 26, - 27, 23, 16, 9, 13, 24, 0, 24, 24, 10, - 71, 83, 49, 118, 73, 109, 116, 113, 115, 55, - 59, 61, 57, 36, -1, -1, -1, -1, -1, 63 +#define YYTABLESIZE 555 +short yytable[] = { 49, + 20, 53, 41, 51, 17, 73, 15, 94, 18, 36, + 63, 123, 91, 92, 21, 49, 119, 120, 127, 1, + 62, 55, 84, 53, 15, 93, 24, 2, 3, 4, + 27, 57, 70, 20, 5, 6, 7, 8, 9, 68, + 68, 69, 31, 59, 20, 32, 33, 34, 71, 73, + 61, 63, 85, 62, 35, 74, 76, 67, 78, 80, + 78, 90, 98, 44, 83, 45, 46, 99, 47, 86, + 100, 101, 102, 68, 87, 48, 114, 109, 62, 103, + 74, 116, 118, 122, 72, 62, 117, 124, 30, 88, + 89, 125, 108, 78, 75, 81, 126, 0, 68, 77, + 27, 0, 79, 0, 82, 0, 0, 0, 0, 0, + 0, 0, 0, 74, 0, 0, 0, 0, 78, 0, + 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 27, 0, 0, 0, 0, 74, 0, + 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 8, 0, 0, 0, 0, 27, 0, + 7, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 9, 0, 0, 0, 0, 0, 0, + 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, + 18, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 10, 0, 0, 0, 0, 0, 0, + 6, 0, 0, 0, 44, 0, 45, 46, 40, 47, + 17, 91, 92, 18, 31, 0, 48, 32, 33, 34, + 44, 0, 45, 46, 93, 47, 35, 53, 53, 0, + 15, 0, 48, 6, 0, 0, 20, 0, 20, 0, + 53, 20, 20, 20, 20, 20, 20, 0, 0, 0, + 20, 20, 20, 20, 20, 20, 62, 104, 62, 0, + 0, 62, 62, 62, 62, 62, 62, 5, 0, 0, + 62, 62, 62, 62, 62, 62, 68, 41, 68, 0, + 0, 68, 68, 68, 68, 68, 68, 0, 0, 0, + 68, 68, 68, 68, 68, 68, 78, 42, 78, 0, + 0, 78, 78, 78, 78, 78, 78, 0, 0, 0, + 78, 78, 78, 78, 78, 78, 74, 0, 74, 0, + 0, 74, 74, 74, 74, 74, 74, 0, 0, 0, + 74, 74, 74, 74, 74, 74, 27, 0, 27, 0, + 0, 27, 27, 27, 27, 27, 27, 0, 0, 0, + 27, 27, 27, 27, 27, 27, 8, 0, 8, 0, + 0, 8, 8, 8, 8, 8, 8, 0, 0, 0, + 8, 8, 8, 8, 8, 8, 9, 0, 9, 0, + 0, 9, 9, 9, 9, 9, 9, 0, 0, 0, + 9, 9, 9, 9, 9, 9, 7, 0, 7, 0, + 0, 7, 7, 7, 7, 7, 7, 0, 0, 0, + 7, 7, 7, 7, 7, 7, 10, 0, 10, 0, + 0, 10, 10, 10, 10, 10, 10, 0, 0, 0, + 10, 10, 10, 10, 10, 10, 18, 0, 18, 0, + 0, 18, 18, 18, 18, 18, 18, 0, 0, 0, + 18, 18, 18, 18, 18, 18, 6, 0, 6, 0, + 0, 6, 6, 6, 6, 6, 6, 0, 0, 0, + 6, 6, 6, 6, 6, 6, 0, 0, 0, 0, + 0, 0, 99, 0, 0, 100, 101, 102, 0, 0, + 0, 0, 5, 0, 103, 5, 5, 5, 0, 0, + 0, 41, 41, 0, 5, 0, 0, 0, 0, 0, + 0, 0, 41, 41, 41, 0, 0, 0, 0, 0, + 0, 42, 42, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 42, 42, 42, }; -/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ -#line 3 "/usr/share/bison/bison.simple" - -/* Skeleton output parser for bison, - - Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -/* As a special exception, when this file is copied by Bison into a - Bison output file, you may use that output file without restriction. - This special exception was added by the Free Software Foundation - in version 1.24 of Bison. */ - -/* This is the parser code that is written into each bison parser when - the %semantic_parser declaration is not specified in the grammar. - It was written by Richard Stallman by simplifying the hairy parser - used when %semantic_parser is specified. */ - -/* All symbols defined below should begin with yy or YY, to avoid - infringing on user name space. This should be done even for local - variables, as they might otherwise be expanded by user macros. - There are some unavoidable exceptions within include files to - define necessary library symbols; they are noted "INFRINGES ON - USER NAME SPACE" below. */ - -#if ! defined (yyoverflow) || defined (YYERROR_VERBOSE) - -/* The parser invokes alloca or malloc; define the necessary symbols. */ - -# if YYSTACK_USE_ALLOCA -# define YYSTACK_ALLOC alloca -# else -# ifndef YYSTACK_USE_ALLOCA -# if defined (alloca) || defined (_ALLOCA_H) -# define YYSTACK_ALLOC alloca -# else -# ifdef __GNUC__ -# define YYSTACK_ALLOC __builtin_alloca -# endif -# endif -# endif -# endif - -# ifdef YYSTACK_ALLOC - /* Pacify GCC's `empty if-body' warning. */ -# define YYSTACK_FREE(Ptr) do { /* empty */; } while (0) -# else -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif -# define YYSTACK_ALLOC malloc -# define YYSTACK_FREE free -# endif -#endif /* ! defined (yyoverflow) || defined (YYERROR_VERBOSE) */ - - -#if (! defined (yyoverflow) \ - && (! defined (__cplusplus) \ - || (YYLTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL))) - -/* A type that is properly aligned for any stack member. */ -union yyalloc -{ - short yyss; - YYSTYPE yyvs; -# if YYLSP_NEEDED - YYLTYPE yyls; -# endif +short yycheck[] = { 33, + 0, 17, 33, 16, 33, 44, 271, 33, 258, 33, + 44, 114, 257, 258, 258, 33, 268, 269, 121, 256, + 0, 58, 61, 33, 33, 270, 258, 264, 265, 266, + 258, 58, 259, 33, 271, 272, 273, 274, 275, 43, + 0, 45, 258, 58, 44, 261, 262, 263, 44, 44, + 58, 44, 263, 33, 270, 61, 61, 61, 61, 61, + 0, 74, 78, 258, 58, 260, 261, 258, 263, 263, + 261, 262, 263, 33, 263, 270, 44, 267, 58, 270, + 0, 44, 44, 113, 49, 36, 109, 115, 10, 71, + 73, 116, 83, 33, 55, 61, 118, -1, 58, 57, + 0, -1, 59, -1, 63, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, 58, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, 58, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, 58, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 33, -1, -1, -1, -1, -1, -1, + 0, -1, -1, -1, 258, -1, 260, 261, 259, 263, + 259, 257, 258, 33, 258, -1, 270, 261, 262, 263, + 258, -1, 260, 261, 270, 263, 270, 257, 258, -1, + 259, -1, 270, 33, -1, -1, 256, -1, 258, -1, + 270, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, 33, 258, -1, + -1, 261, 262, 263, 264, 265, 266, 33, -1, -1, + 270, 271, 272, 273, 274, 275, 256, 33, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, 33, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, 256, -1, 258, -1, + -1, 261, 262, 263, 264, 265, 266, -1, -1, -1, + 270, 271, 272, 273, 274, 275, -1, -1, -1, -1, + -1, -1, 258, -1, -1, 261, 262, 263, -1, -1, + -1, -1, 258, -1, 270, 261, 262, 263, -1, -1, + -1, 257, 258, -1, 270, -1, -1, -1, -1, -1, + -1, -1, 268, 269, 270, -1, -1, -1, -1, -1, + -1, 257, 258, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 268, 269, 270, }; - -/* The size of the maximum gap between one aligned stack and the next. */ -# define YYSTACK_GAP_MAX (sizeof (union yyalloc) - 1) - -/* The size of an array large to enough to hold all stacks, each with - N elements. */ -# if YYLSP_NEEDED -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE) + sizeof (YYLTYPE)) \ - + 2 * YYSTACK_GAP_MAX) -# else -# define YYSTACK_BYTES(N) \ - ((N) * (sizeof (short) + sizeof (YYSTYPE)) \ - + YYSTACK_GAP_MAX) -# endif - -/* Copy COUNT objects from FROM to TO. The source and destination do - not overlap. */ -# ifndef YYCOPY -# if 1 < __GNUC__ -# define YYCOPY(To, From, Count) \ - __builtin_memcpy (To, From, (Count) * sizeof (*(From))) -# else -# define YYCOPY(To, From, Count) \ - do \ - { \ - register YYSIZE_T yyi; \ - for (yyi = 0; yyi < (Count); yyi++) \ - (To)[yyi] = (From)[yyi]; \ - } \ - while (0) -# endif -# endif - -/* Relocate STACK from its old location to the new one. The - local variables YYSIZE and YYSTACKSIZE give the old and new number of - elements in the stack, and YYPTR gives the new location of the - stack. Advance YYPTR to a properly aligned location for the next - stack. */ -# define YYSTACK_RELOCATE(Stack) \ - do \ - { \ - YYSIZE_T yynewbytes; \ - YYCOPY (&yyptr->Stack, Stack, yysize); \ - Stack = &yyptr->Stack; \ - yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAX; \ - yyptr += yynewbytes / sizeof (*yyptr); \ - } \ - while (0) - +#define YYFINAL 10 +#ifndef YYDEBUG +#define YYDEBUG 0 #endif - - -#if ! defined (YYSIZE_T) && defined (__SIZE_TYPE__) -# define YYSIZE_T __SIZE_TYPE__ +#define YYMAXTOKEN 276 +#if YYDEBUG +#if defined(__cplusplus) || __STDC__ +const char * const yyname[] = +#else +char *yyname[] = #endif -#if ! defined (YYSIZE_T) && defined (size_t) -# define YYSIZE_T size_t + { +"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","RUNAS","NOPASSWD","PASSWD","ALL","COMMENT", +"HOSTALIAS","CMNDALIAS","USERALIAS","RUNASALIAS","ERROR", +}; +#if defined(__cplusplus) || __STDC__ +const char * const yyrule[] = +#else +char *yyrule[] = #endif -#if ! defined (YYSIZE_T) -# if defined (__STDC__) || defined (__cplusplus) -# include /* INFRINGES ON USER NAME SPACE */ -# define YYSIZE_T size_t -# endif + {"$accept : file", +"file : entry", +"file : file 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_HOST $$3 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 nopasswd opcmnd", +"opcmnd : cmnd", +"$$4 :", +"opcmnd : '!' $$4 cmnd", +"runasspec :", +"runasspec : RUNAS runaslist", +"runaslist : oprunasuser", +"runaslist : runaslist ',' oprunasuser", +"oprunasuser : runasuser", +"$$5 :", +"oprunasuser : '!' $$5 runasuser", +"runasuser : WORD", +"runasuser : USERGROUP", +"runasuser : NETGROUP", +"runasuser : ALIAS", +"runasuser : ALL", +"nopasswd :", +"nopasswd : NOPASSWD", +"nopasswd : PASSWD", +"cmnd : ALL", +"cmnd : ALIAS", +"cmnd : COMMAND", +"hostaliases : hostalias", +"hostaliases : hostaliases ':' hostalias", +"$$6 :", +"hostalias : ALIAS $$6 '=' hostlist", +"hostlist : ophost", +"hostlist : hostlist ',' ophost", +"cmndaliases : cmndalias", +"cmndaliases : cmndaliases ':' cmndalias", +"$$7 :", +"cmndalias : ALIAS $$7 '=' cmndlist", +"cmndlist : opcmnd", +"cmndlist : cmndlist ',' opcmnd", +"runasaliases : runasalias", +"runasaliases : runasaliases ':' runasalias", +"$$8 :", +"runasalias : ALIAS $$8 '=' runaslist", +"useraliases : useralias", +"useraliases : useraliases ':' useralias", +"$$9 :", +"useralias : ALIAS $$9 '=' userlist", +"userlist : opuser", +"userlist : userlist ',' opuser", +"opuser : user", +"opuser : '!' user", +"user : WORD", +"user : USERGROUP", +"user : NETGROUP", +"user : ALIAS", +"user : ALL", +}; #endif -#if ! defined (YYSIZE_T) -# define YYSIZE_T unsigned int +#ifdef YYSTACKSIZE +#undef YYMAXDEPTH +#define YYMAXDEPTH YYSTACKSIZE +#else +#ifdef YYMAXDEPTH +#define YYSTACKSIZE YYMAXDEPTH +#else +#define YYSTACKSIZE 10000 +#define YYMAXDEPTH 10000 #endif - -#define yyerrok (yyerrstatus = 0) -#define yyclearin (yychar = YYEMPTY) -#define YYEMPTY -2 -#define YYEOF 0 -#define YYACCEPT goto yyacceptlab -#define YYABORT goto yyabortlab -#define YYERROR goto yyerrlab1 -/* Like YYERROR except do call yyerror. This remains here temporarily - to ease the transition to the new meaning of YYERROR, for GCC. - Once GCC version 2 has supplanted version 1, this can go. */ -#define YYFAIL goto yyerrlab -#define YYRECOVERING() (!!yyerrstatus) -#define YYBACKUP(Token, Value) \ -do \ - if (yychar == YYEMPTY && yylen == 1) \ - { \ - yychar = (Token); \ - yylval = (Value); \ - yychar1 = YYTRANSLATE (yychar); \ - YYPOPSTACK; \ - goto yybackup; \ - } \ - else \ - { \ - yyerror ("syntax error: cannot back up"); \ - YYERROR; \ - } \ -while (0) - -#define YYTERROR 1 -#define YYERRCODE 256 - - -/* YYLLOC_DEFAULT -- Compute the default location (before the actions - are run). - - When YYLLOC_DEFAULT is run, CURRENT is set the location of the - first token. By default, to implement support for ranges, extend - its range to the last symbol. */ - -#ifndef YYLLOC_DEFAULT -# define YYLLOC_DEFAULT(Current, Rhs, N) \ - Current.last_line = Rhs[N].last_line; \ - Current.last_column = Rhs[N].last_column; #endif - - -/* YYLEX -- calling `yylex' with the right arguments. */ - -#if YYPURE -# if YYLSP_NEEDED -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, &yylloc, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval, &yylloc) -# endif -# else /* !YYLSP_NEEDED */ -# ifdef YYLEX_PARAM -# define YYLEX yylex (&yylval, YYLEX_PARAM) -# else -# define YYLEX yylex (&yylval) -# endif -# endif /* !YYLSP_NEEDED */ -#else /* !YYPURE */ -# define YYLEX yylex () -#endif /* !YYPURE */ - - -/* Enable debugging if requested. */ -#if YYDEBUG - -# ifndef YYFPRINTF -# include /* INFRINGES ON USER NAME SPACE */ -# define YYFPRINTF fprintf -# endif - -# define YYDPRINTF(Args) \ -do { \ - if (yydebug) \ - YYFPRINTF Args; \ -} while (0) -/* Nonzero means print parse trace. It is left uninitialized so that - multiple parsers can coexist. */ +#define YYINITSTACKSIZE 200 int yydebug; -#else /* !YYDEBUG */ -# define YYDPRINTF(Args) -#endif /* !YYDEBUG */ +int yynerrs; +int yyerrflag; +int yychar; +short *yyssp; +YYSTYPE *yyvsp; +YYSTYPE yyval; +YYSTYPE yylval; +short *yyss; +short *yysslim; +YYSTYPE *yyvs; +int yystacksize; +#line 844 "parse.yacc" -/* YYINITDEPTH -- initial size of the parser's stacks. */ -#ifndef YYINITDEPTH -# define YYINITDEPTH 200 -#endif +#define MOREALIASES (32) +aliasinfo *aliases = NULL; +size_t naliases = 0; +size_t nslots = 0; -/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only - if the built-in stack extension method is used). - Do not make this value too large; the results are undefined if - SIZE_MAX < YYSTACK_BYTES (YYMAXDEPTH) - evaluated with infinite-precision integer arithmetic. */ +/* + * 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; -#if YYMAXDEPTH == 0 -# undef YYMAXDEPTH -#endif + ai1 = (aliasinfo *) a1; + ai2 = (aliasinfo *) a2; + if ((r = strcmp(ai1->name, ai2->name)) == 0) + r = ai1->type - ai2->type; -#ifndef YYMAXDEPTH -# define YYMAXDEPTH 10000 -#endif - -#ifdef YYERROR_VERBOSE - -# ifndef yystrlen -# if defined (__GLIBC__) && defined (_STRING_H) -# define yystrlen strlen -# else -/* Return the length of YYSTR. */ -static YYSIZE_T -# if defined (__STDC__) || defined (__cplusplus) -yystrlen (const char *yystr) -# else -yystrlen (yystr) - const char *yystr; -# endif -{ - register const char *yys = yystr; - - while (*yys++ != '\0') - continue; - - return yys - yystr - 1; + return(r); } -# endif -# endif -# ifndef yystpcpy -# if defined (__GLIBC__) && defined (_STRING_H) && defined (_GNU_SOURCE) -# define yystpcpy stpcpy -# else -/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in - YYDEST. */ -static char * -# if defined (__STDC__) || defined (__cplusplus) -yystpcpy (char *yydest, const char *yysrc) -# else -yystpcpy (yydest, yysrc) - char *yydest; - const char *yysrc; -# endif -{ - register char *yyd = yydest; - register const char *yys = yysrc; - - while ((*yyd++ = *yys++) != '\0') - continue; - - return yyd - 1; -} -# endif -# endif -#endif - -#line 315 "/usr/share/bison/bison.simple" - - -/* The user can define YYPARSE_PARAM as the name of an argument to be passed - into yyparse. The argument should have type void *. - It should actually point to an object. - Grammar actions can access the variable by casting it - to the proper pointer type. */ - -#ifdef YYPARSE_PARAM -# if defined (__STDC__) || defined (__cplusplus) -# define YYPARSE_PARAM_ARG void *YYPARSE_PARAM -# define YYPARSE_PARAM_DECL -# else -# define YYPARSE_PARAM_ARG YYPARSE_PARAM -# define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; -# endif -#else /* !YYPARSE_PARAM */ -# define YYPARSE_PARAM_ARG -# define YYPARSE_PARAM_DECL -#endif /* !YYPARSE_PARAM */ - -/* Prevent warning if -Wstrict-prototypes. */ -#ifdef __GNUC__ -# ifdef YYPARSE_PARAM -int yyparse (void *); -# else -int yyparse (void); -# endif -#endif +/* + * Compare two generic_alias structures, strcmp() style. + */ +static int +genaliascmp(entry, key) + const VOID *entry, *key; +{ + int r; + struct generic_alias *ga1, *ga2; -/* YY_DECL_VARIABLES -- depending whether we use a pure parser, - variables are global, or local to YYPARSE. */ - -#define YY_DECL_NON_LSP_VARIABLES \ -/* The lookahead symbol. */ \ -int yychar; \ - \ -/* The semantic value of the lookahead symbol. */ \ -YYSTYPE yylval; \ - \ -/* Number of parse errors so far. */ \ -int yynerrs; + ga1 = (struct generic_alias *) key; + ga2 = (struct generic_alias *) entry; + if ((r = strcmp(ga1->alias, ga2->alias)) == 0) + r = ga1->type - ga2->type; -#if YYLSP_NEEDED -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES \ - \ -/* Location data for the lookahead symbol. */ \ -YYLTYPE yylloc; -#else -# define YY_DECL_VARIABLES \ -YY_DECL_NON_LSP_VARIABLES -#endif + return(r); +} -/* If nonreentrant, generate the variables here. */ +/* + * 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 !YYPURE -YY_DECL_VARIABLES -#endif /* !YYPURE */ + if (naliases >= nslots && !more_aliases()) { + (void) snprintf(s, sizeof(s), "Out of memory defining alias `%s'", + alias); + yyerror(s); + return(FALSE); + } -int -yyparse (YYPARSE_PARAM_ARG) - YYPARSE_PARAM_DECL -{ - /* If reentrant, generate the variables here. */ -#if YYPURE - YY_DECL_VARIABLES -#endif /* !YYPURE */ - - register int yystate; - register int yyn; - int yyresult; - /* Number of tokens to shift before error messages enabled. */ - int yyerrstatus; - /* Lookahead token as an internal (translated) token number. */ - int yychar1 = 0; - - /* Three stacks and their tools: - `yyss': related to states, - `yyvs': related to semantic values, - `yyls': related to locations. - - Refer to the stacks thru separate pointers, to allow yyoverflow - to reallocate them elsewhere. */ - - /* The state stack. */ - short yyssa[YYINITDEPTH]; - short *yyss = yyssa; - register short *yyssp; - - /* The semantic value stack. */ - YYSTYPE yyvsa[YYINITDEPTH]; - YYSTYPE *yyvs = yyvsa; - register YYSTYPE *yyvsp; - -#if YYLSP_NEEDED - /* The location stack. */ - YYLTYPE yylsa[YYINITDEPTH]; - YYLTYPE *yyls = yylsa; - YYLTYPE *yylsp; -#endif + ai.type = type; + ai.val = val; + ai.name = estrdup(alias); + onaliases = naliases; -#if YYLSP_NEEDED -# define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) -#else -# define YYPOPSTACK (yyvsp--, yyssp--) -#endif + 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); + } - YYSIZE_T yystacksize = YYINITDEPTH; + return(TRUE); +} +/* + * Searches for the named alias of the specified type. + */ +static aliasinfo * +find_alias(alias, type) + char *alias; + int type; +{ + aliasinfo ai; - /* The variables used to return semantic value and location from the - action routines. */ - YYSTYPE yyval; -#if YYLSP_NEEDED - YYLTYPE yyloc; -#endif + ai.name = alias; + ai.type = type; - /* When reducing, the number of symbols on the RHS of the reduced - rule. */ - int yylen; + return((aliasinfo *) lfind((VOID *)&ai, (VOID *)aliases, &naliases, + sizeof(ai), aliascmp)); +} - YYDPRINTF ((stderr, "Starting parse\n")); +/* + * Allocates more space for the aliases list. + */ +static int +more_aliases() +{ - yystate = 0; - yyerrstatus = 0; - yynerrs = 0; - yychar = YYEMPTY; /* Cause a token to be read. */ + nslots += MOREALIASES; + if (nslots == MOREALIASES) + aliases = (aliasinfo *) malloc(nslots * sizeof(aliasinfo)); + else + aliases = (aliasinfo *) realloc(aliases, nslots * sizeof(aliasinfo)); - /* Initialize stack pointers. - Waste one element of value and location stack - so that they stay on the same level as the state stack. - The wasted elements are never initialized. */ + return(aliases != NULL); +} - yyssp = yyss; - yyvsp = yyvs; -#if YYLSP_NEEDED - yylsp = yyls; -#endif - goto yysetstate; - -/*------------------------------------------------------------. -| yynewstate -- Push a new state, which is found in yystate. | -`------------------------------------------------------------*/ - yynewstate: - /* In all cases, when you get here, the value and location stacks - have just been pushed. so pushing a state here evens the stacks. - */ - yyssp++; +/* + * Lists the contents of the aliases list. + */ +void +dumpaliases() +{ + size_t n; - yysetstate: - *yyssp = yystate; + for (n = 0; n < naliases; n++) { + if (aliases[n].val == -1) + continue; - if (yyssp >= yyss + yystacksize - 1) - { - /* Get the current used size of the three stacks, in elements. */ - YYSIZE_T yysize = yyssp - yyss + 1; - -#ifdef yyoverflow - { - /* Give user a chance to reallocate the stack. Use copies of - these so that the &'s don't force the real ones into - memory. */ - YYSTYPE *yyvs1 = yyvs; - short *yyss1 = yyss; - - /* Each stack pointer address is followed by the size of the - data in use in that stack, in bytes. */ -# if YYLSP_NEEDED - YYLTYPE *yyls1 = yyls; - /* This used to be a conditional around just the two extra args, - but that might be undefined if yyoverflow is a macro. */ - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yyls1, yysize * sizeof (*yylsp), - &yystacksize); - yyls = yyls1; -# else - yyoverflow ("parser stack overflow", - &yyss1, yysize * sizeof (*yyssp), - &yyvs1, yysize * sizeof (*yyvsp), - &yystacksize); -# endif - yyss = yyss1; - yyvs = yyvs1; - } -#else /* no yyoverflow */ -# ifndef YYSTACK_RELOCATE - goto yyoverflowlab; -# else - /* Extend the stack our own way. */ - if (yystacksize >= YYMAXDEPTH) - goto yyoverflowlab; - yystacksize *= 2; - if (yystacksize > YYMAXDEPTH) - yystacksize = YYMAXDEPTH; - - { - short *yyss1 = yyss; - union yyalloc *yyptr = - (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize)); - if (! yyptr) - goto yyoverflowlab; - YYSTACK_RELOCATE (yyss); - YYSTACK_RELOCATE (yyvs); -# if YYLSP_NEEDED - YYSTACK_RELOCATE (yyls); -# endif -# undef YYSTACK_RELOCATE - if (yyss1 != yyssa) - YYSTACK_FREE (yyss1); - } -# endif -#endif /* no yyoverflow */ + switch (aliases[n].type) { + case HOST_ALIAS: + (void) puts("HOST_ALIAS"); + break; - yyssp = yyss + yysize - 1; - yyvsp = yyvs + yysize - 1; -#if YYLSP_NEEDED - yylsp = yyls + yysize - 1; -#endif + case CMND_ALIAS: + (void) puts("CMND_ALIAS"); + break; - YYDPRINTF ((stderr, "Stack size increased to %lu\n", - (unsigned long int) yystacksize)); + case USER_ALIAS: + (void) puts("USER_ALIAS"); + break; - if (yyssp >= yyss + yystacksize - 1) - YYABORT; + case RUNAS_ALIAS: + (void) puts("RUNAS_ALIAS"); + break; + } + (void) printf("\t%s: %d\n", aliases[n].name, aliases[n].val); } +} - YYDPRINTF ((stderr, "Entering state %d\n", yystate)); +/* + * Lists the contents of cm_list and ga_list for `sudo -l'. + */ +void +list_matches() +{ + int i; + char *p; + struct generic_alias *ga, key; - goto yybackup; + (void) printf("User %s may run the following commands on this host:\n", + user_name); + for (i = 0; i < cm_list_len; i++) { + /* Print the runas list. */ + (void) fputs(" ", stdout); + if (cm_list[i].runas) { + (void) putchar('('); + p = strtok(cm_list[i].runas, ", "); + do { + if (p != cm_list[i].runas) + (void) fputs(", ", stdout); -/*-----------. -| yybackup. | -`-----------*/ -yybackup: + 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_str(I_RUNAS_DEFAULT)); + } -/* Do appropriate processing given the current state. */ -/* Read a lookahead token if we need one and don't already have one. */ -/* yyresume: */ - - /* First try to decide what to do without reference to lookahead token. */ - - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yydefault; + /* Is a password required? */ + if (cm_list[i].nopasswd == TRUE && def_flag(I_AUTHENTICATE)) + (void) fputs("NOPASSWD: ", stdout); + else if (cm_list[i].nopasswd == FALSE && !def_flag(I_AUTHENTICATE)) + (void) fputs("PASSWD: ", stdout); - /* Not known => get a lookahead token if don't already have one. */ + /* Print the actual command or expanded Cmnd_Alias. */ + key.alias = cm_list[i].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[i].cmnd); + } - /* yychar is either YYEMPTY or YYEOF - or a valid token in external form. */ + /* Be nice and free up space now that we are done. */ + for (i = 0; i < ga_list_len; i++) { + free(ga_list[i].alias); + free(ga_list[i].entries); + } + free(ga_list); + ga_list = NULL; - if (yychar == YYEMPTY) - { - YYDPRINTF ((stderr, "Reading a token: ")); - yychar = YYLEX; + for (i = 0; i < cm_list_len; i++) { + free(cm_list[i].runas); + free(cm_list[i].cmnd); } + free(cm_list); + cm_list = NULL; + cm_list_len = 0; + cm_list_size = 0; +} - /* Convert token to internal form (in yychar1) for indexing tables with */ +/* + * 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; - if (yychar <= 0) /* This means end of input. */ - { - yychar1 = 0; - yychar = YYEOF; /* Don't call YYLEX any more */ + /* + * 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; - YYDPRINTF ((stderr, "Now at end of input.\n")); + /* Assumes dst will be NULL if not set. */ + if (dst == NULL) { + dst = (char *) emalloc(BUFSIZ); + *dst_size = BUFSIZ; + *dst_len = 0; + *dstp = dst; } - else - { - yychar1 = YYTRANSLATE (yychar); -#if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables - which are defined only if `YYDEBUG' is set. */ - if (yydebug) - { - YYFPRINTF (stderr, "Next token is %d (%s", - yychar, yytname[yychar1]); - /* Give the individual parser a way to print the precise - meaning of a token, for further debugging info. */ -# ifdef YYPRINT - YYPRINT (stderr, yychar, yylval); -# endif - YYFPRINTF (stderr, ")\n"); - } -#endif - } + /* Allocate more space if necessary. */ + if (*dst_size <= *dst_len + src_len) { + while (*dst_size <= *dst_len + src_len) + *dst_size += BUFSIZ; - yyn += yychar1; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) - goto yydefault; + dst = (char *) erealloc(dst, *dst_size); + *dstp = dst; + } - yyn = yytable[yyn]; + /* Copy src -> dst adding a separator if appropriate and adjust len. */ + dst += *dst_len; + *dst_len += src_len; + *dst = '\0'; + if (separator) + (void) strcat(dst, separator); + (void) strcat(dst, src); +} - /* yyn is what to do for this token type in this state. - Negative => reduce, -yyn is rule number. - Positive => shift, yyn is new state. - New state is final state => don't bother to shift, - just return success. - 0, or most negative number => error. */ +/* + * Frees up space used by the aliases list and resets the associated counters. + */ +void +reset_aliases() +{ + size_t n; - if (yyn < 0) - { - if (yyn == YYFLAG) - goto yyerrlab; - yyn = -yyn; - goto yyreduce; + if (aliases) { + for (n = 0; n < naliases; n++) + free(aliases[n].name); + free(aliases); + aliases = NULL; } - else if (yyn == 0) - goto yyerrlab; + naliases = nslots = 0; +} - if (yyn == YYFINAL) - YYACCEPT; +/* + * Increments ga_list_len, allocating more space as necessary. + */ +static void +expand_ga_list() +{ - /* Shift the lookahead token. */ - YYDPRINTF ((stderr, "Shifting token %d (%s), ", - yychar, yytname[yychar1])); + if (++ga_list_len >= ga_list_size) { + while ((ga_list_size += STACKINCREMENT) < ga_list_len) + ; + ga_list = (struct generic_alias *) + erealloc(ga_list, sizeof(struct generic_alias) * ga_list_size); + } - /* Discard the token being shifted unless it is eof. */ - if (yychar != YYEOF) - yychar = YYEMPTY; + ga_list[ga_list_len - 1].entries = NULL; +} - *++yyvsp = yylval; -#if YYLSP_NEEDED - *++yylsp = yylloc; -#endif +/* + * Increments cm_list_len, allocating more space as necessary. + */ +static void +expand_match_list() +{ - /* Count tokens shifted since error; after three, turn off error - status. */ - if (yyerrstatus) - yyerrstatus--; + 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 *) + erealloc(cm_list, sizeof(struct command_match) * cm_list_size); + } - yystate = yyn; - goto yynewstate; + cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL; + cm_list[cm_list_len].nopasswd = FALSE; +} +/* + * Frees up spaced used by a previous parser run and allocates new space + * for various data structures. + */ +void +init_parser() +{ -/*-----------------------------------------------------------. -| yydefault -- do the default action for the current state. | -`-----------------------------------------------------------*/ -yydefault: - yyn = yydefact[yystate]; - if (yyn == 0) - goto yyerrlab; - goto yyreduce; + /* Free up old data structures if we run the parser more than once. */ + if (match) { + free(match); + match = NULL; + top = 0; + parse_error = FALSE; + errorlineno = -1; + sudolineno = 1; + } + /* Allocate space for the matching stack. */ + stacksize = STACKINCREMENT; + match = (struct matchstack *) emalloc(sizeof(struct matchstack) * stacksize); -/*-----------------------------. -| yyreduce -- Do a reduction. | -`-----------------------------*/ -yyreduce: - /* yyn is the number of a rule to reduce with. */ - yylen = yyr2[yyn]; - - /* If YYLEN is nonzero, implement the default value of the action: - `$$ = $1'. - - Otherwise, the following line sets YYVAL to the semantic value of - the lookahead token. This behavior is undocumented and Bison - users should not rely upon it. Assigning to YYVAL - unconditionally makes the parser a bit smaller, and it avoids a - GCC warning that YYVAL may be used uninitialized. */ - yyval = yyvsp[1-yylen]; - -#if YYLSP_NEEDED - /* Similarly for the default location. Let the user run additional - commands if for instance locations are ranges. */ - yyloc = yylsp[1-yylen]; - YYLLOC_DEFAULT (yyloc, (yylsp - yylen), yylen); + /* Allocate space for the match list (for `sudo -l'). */ + if (printmatches == TRUE) + expand_match_list(); +} +#line 940 "sudo.tab.c" +/* allocate initial stack or double stack size, up to YYMAXDEPTH */ +#if defined(__cplusplus) || __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) || __STDC__ +yyparse(void) +#else +yyparse() +#endif +{ + int yym, yyn, yystate; #if YYDEBUG - /* We have to keep this `#if YYDEBUG', since we use variables which - are defined only if `YYDEBUG' is set. */ - if (yydebug) +#if defined(__cplusplus) || __STDC__ + const char *yys; +#else /* !(defined(__cplusplus) || __STDC__) */ + char *yys; +#endif /* !(defined(__cplusplus) || __STDC__) */ + + if ((yys = getenv("YYDEBUG"))) { - int yyi; + yyn = *yys; + if (yyn >= '0' && yyn <= '9') + yydebug = yyn - '0'; + } +#endif /* YYDEBUG */ - YYFPRINTF (stderr, "Reducing via rule %d (line %d), ", - yyn, yyrline[yyn]); + yynerrs = 0; + yyerrflag = 0; + yychar = (-1); - /* Print the symbols being reduced, and their result. */ - for (yyi = yyprhs[yyn]; yyrhs[yyi] > 0; yyi++) - YYFPRINTF (stderr, "%s ", yytname[yyrhs[yyi]]); - YYFPRINTF (stderr, " -> %s\n", yytname[yyr1[yyn]]); + 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 - - switch (yyn) { - +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 3: #line 264 "parse.yacc" { ; } - break; +break; case 4: #line 266 "parse.yacc" { yyerrok; } - break; +break; case 5: #line 267 "parse.yacc" { push; } - break; +break; case 6: #line 267 "parse.yacc" { while (top && user_matches != TRUE) pop; } - break; +break; case 7: #line 272 "parse.yacc" { ; } - break; +break; case 8: #line 274 "parse.yacc" { ; } - break; +break; case 9: #line 276 "parse.yacc" { ; } - break; +break; case 10: #line 278 "parse.yacc" { ; } - break; +break; case 11: #line 280 "parse.yacc" { ; } - break; +break; case 13: #line 285 "parse.yacc" { defaults_matches = TRUE; } - break; +break; case 14: #line 288 "parse.yacc" { push; } - break; +break; case 15: #line 288 "parse.yacc" { defaults_matches = user_matches; pop; } - break; +break; case 16: #line 292 "parse.yacc" { push; } - break; +break; case 17: #line 292 "parse.yacc" { defaults_matches = host_matches; pop; } - break; +break; case 20: #line 301 "parse.yacc" { @@ -1279,7 +1215,7 @@ case 20: } free(yyvsp[0].string); } - break; +break; case 21: #line 309 "parse.yacc" { @@ -1290,7 +1226,7 @@ case 21: } free(yyvsp[0].string); } - break; +break; case 22: #line 317 "parse.yacc" { @@ -1302,7 +1238,7 @@ case 22: free(yyvsp[-2].string); free(yyvsp[0].string); } - break; +break; case 23: #line 326 "parse.yacc" { @@ -1314,7 +1250,7 @@ case 23: free(yyvsp[-2].string); free(yyvsp[0].string); } - break; +break; case 24: #line 335 "parse.yacc" { @@ -1326,7 +1262,7 @@ case 24: free(yyvsp[-2].string); free(yyvsp[0].string); } - break; +break; case 27: #line 349 "parse.yacc" { @@ -1342,27 +1278,27 @@ case 27: else no_passwd = TRUE; } - break; +break; case 28: #line 364 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) host_matches = yyvsp[0].BOOLEAN; } - break; +break; case 29: #line 368 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) host_matches = ! yyvsp[0].BOOLEAN; } - break; +break; case 30: #line 373 "parse.yacc" { yyval.BOOLEAN = TRUE; } - break; +break; case 31: #line 376 "parse.yacc" { @@ -1372,7 +1308,7 @@ case 31: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 32: #line 383 "parse.yacc" { @@ -1382,7 +1318,7 @@ case 32: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 33: #line 390 "parse.yacc" { @@ -1392,7 +1328,7 @@ case 33: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 34: #line 397 "parse.yacc" { @@ -1417,7 +1353,7 @@ case 34: } free(yyvsp[0].string); } - break; +break; case 37: #line 425 "parse.yacc" { @@ -1445,14 +1381,14 @@ case 37: pushcp; cmnd_matches = -1; } - break; +break; case 38: #line 452 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) cmnd_matches = yyvsp[0].BOOLEAN; } - break; +break; case 39: #line 456 "parse.yacc" { @@ -1464,14 +1400,14 @@ case 39: append_cmnd("!", NULL); } } - break; +break; case 40: #line 464 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) cmnd_matches = ! yyvsp[0].BOOLEAN; } - break; +break; case 41: #line 470 "parse.yacc" { @@ -1497,17 +1433,17 @@ case 41: runas_matches = (strcmp(*user_runas, def_str(I_RUNAS_DEFAULT)) == 0); } - break; +break; case 42: #line 493 "parse.yacc" { runas_matches = (yyvsp[0].BOOLEAN == TRUE ? TRUE : FALSE); } - break; +break; case 43: #line 498 "parse.yacc" { ; } - break; +break; case 44: #line 499 "parse.yacc" { @@ -1517,11 +1453,11 @@ case 44: else yyval.BOOLEAN = yyvsp[-2].BOOLEAN; } - break; +break; case 45: #line 508 "parse.yacc" { ; } - break; +break; case 46: #line 509 "parse.yacc" { @@ -1533,14 +1469,14 @@ case 46: append_runas("!", ", "); } } - break; +break; case 47: #line 517 "parse.yacc" { /* Set $$ to the negation of runasuser */ yyval.BOOLEAN = (yyvsp[0].BOOLEAN == -1 ? -1 : ! yyvsp[0].BOOLEAN); } - break; +break; case 48: #line 522 "parse.yacc" { @@ -1557,7 +1493,7 @@ case 48: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 49: #line 536 "parse.yacc" { @@ -1574,7 +1510,7 @@ case 49: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 50: #line 550 "parse.yacc" { @@ -1591,7 +1527,7 @@ case 50: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 51: #line 564 "parse.yacc" { @@ -1623,7 +1559,7 @@ case 51: } free(yyvsp[0].string); } - break; +break; case 52: #line 593 "parse.yacc" { @@ -1636,7 +1572,7 @@ case 52: } yyval.BOOLEAN = TRUE; } - break; +break; case 53: #line 605 "parse.yacc" { @@ -1649,7 +1585,7 @@ case 53: cm_list[cm_list_len].nopasswd = FALSE; } } - break; +break; case 54: #line 615 "parse.yacc" { @@ -1658,7 +1594,7 @@ case 54: user_matches == TRUE) cm_list[cm_list_len].nopasswd = TRUE; } - break; +break; case 55: #line 621 "parse.yacc" { @@ -1667,7 +1603,7 @@ case 55: user_matches == TRUE) cm_list[cm_list_len].nopasswd = FALSE; } - break; +break; case 56: #line 629 "parse.yacc" { @@ -1682,10 +1618,14 @@ case 56: } yyval.BOOLEAN = TRUE; + + if (safe_cmnd) + free(safe_cmnd); + safe_cmnd = estrdup(user_cmnd); } - break; +break; case 57: -#line 642 "parse.yacc" +#line 646 "parse.yacc" { aliasinfo *aip; @@ -1715,9 +1655,9 @@ case 57: } free(yyvsp[0].string); } - break; +break; case 58: -#line 671 "parse.yacc" +#line 675 "parse.yacc" { if (printmatches == TRUE) { if (in_alias == TRUE) { @@ -1744,22 +1684,22 @@ case 58: if (yyvsp[0].command.args) free(yyvsp[0].command.args); } - break; +break; case 61: -#line 703 "parse.yacc" +#line 707 "parse.yacc" { push; } - break; +break; case 62: -#line 703 "parse.yacc" +#line 707 "parse.yacc" { if ((host_matches != -1 || pedantic) && !add_alias(yyvsp[-3].string, HOST_ALIAS, host_matches)) YYERROR; pop; } - break; +break; case 67: -#line 719 "parse.yacc" +#line 723 "parse.yacc" { push; if (printmatches == TRUE) { @@ -1770,9 +1710,9 @@ case 67: ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string); } } - break; +break; case 68: -#line 728 "parse.yacc" +#line 732 "parse.yacc" { if ((cmnd_matches != -1 || pedantic) && !add_alias(yyvsp[-3].string, CMND_ALIAS, cmnd_matches)) @@ -1783,13 +1723,13 @@ case 68: if (printmatches == TRUE) in_alias = FALSE; } - break; +break; case 69: -#line 740 "parse.yacc" +#line 744 "parse.yacc" { ; } - break; +break; case 73: -#line 748 "parse.yacc" +#line 752 "parse.yacc" { if (printmatches == TRUE) { in_alias = TRUE; @@ -1799,9 +1739,9 @@ case 73: ga_list[ga_list_len-1].alias = estrdup(yyvsp[0].string); } } - break; +break; case 74: -#line 756 "parse.yacc" +#line 760 "parse.yacc" { if ((yyvsp[0].BOOLEAN != -1 || pedantic) && !add_alias(yyvsp[-3].string, RUNAS_ALIAS, yyvsp[0].BOOLEAN)) @@ -1811,13 +1751,13 @@ case 74: if (printmatches == TRUE) in_alias = FALSE; } - break; +break; case 77: -#line 771 "parse.yacc" +#line 775 "parse.yacc" { push; } - break; +break; case 78: -#line 771 "parse.yacc" +#line 775 "parse.yacc" { if ((user_matches != -1 || pedantic) && !add_alias(yyvsp[-3].string, USER_ALIAS, user_matches)) @@ -1825,23 +1765,23 @@ case 78: pop; free(yyvsp[-3].string); } - break; +break; case 81: -#line 784 "parse.yacc" +#line 788 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) user_matches = yyvsp[0].BOOLEAN; } - break; +break; case 82: -#line 788 "parse.yacc" +#line 792 "parse.yacc" { if (yyvsp[0].BOOLEAN != -1) user_matches = ! yyvsp[0].BOOLEAN; } - break; +break; case 83: -#line 793 "parse.yacc" +#line 797 "parse.yacc" { if (strcmp(yyvsp[0].string, user_name) == 0) yyval.BOOLEAN = TRUE; @@ -1849,9 +1789,9 @@ case 83: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 84: -#line 800 "parse.yacc" +#line 804 "parse.yacc" { if (usergr_matches(yyvsp[0].string, user_name)) yyval.BOOLEAN = TRUE; @@ -1859,9 +1799,9 @@ case 84: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 85: -#line 807 "parse.yacc" +#line 811 "parse.yacc" { if (netgr_matches(yyvsp[0].string, NULL, NULL, user_name)) yyval.BOOLEAN = TRUE; @@ -1869,9 +1809,9 @@ case 85: yyval.BOOLEAN = -1; free(yyvsp[0].string); } - break; +break; case 86: -#line 814 "parse.yacc" +#line 818 "parse.yacc" { aliasinfo *aip = find_alias(yyvsp[0].string, USER_ALIAS); @@ -1892,595 +1832,67 @@ case 86: } free(yyvsp[0].string); } - break; +break; case 87: -#line 834 "parse.yacc" +#line 838 "parse.yacc" { yyval.BOOLEAN = TRUE; } - break; -} - -#line 705 "/usr/share/bison/bison.simple" - - - yyvsp -= yylen; - yyssp -= yylen; -#if YYLSP_NEEDED - yylsp -= yylen; -#endif - -#if YYDEBUG - if (yydebug) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); - } -#endif - - *++yyvsp = yyval; -#if YYLSP_NEEDED - *++yylsp = yyloc; -#endif - - /* Now `shift' the result of the reduction. Determine what state - that goes to, based on the state we popped back to and the rule - number reduced by. */ - - yyn = yyr1[yyn]; - - yystate = yypgoto[yyn - YYNTBASE] + *yyssp; - if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) - yystate = yytable[yystate]; - else - yystate = yydefgoto[yyn - YYNTBASE]; - - goto yynewstate; - - -/*------------------------------------. -| yyerrlab -- here on detecting error | -`------------------------------------*/ -yyerrlab: - /* If not already recovering from an error, report this error. */ - if (!yyerrstatus) - { - ++yynerrs; - -#ifdef YYERROR_VERBOSE - yyn = yypact[yystate]; - - if (yyn > YYFLAG && yyn < YYLAST) - { - YYSIZE_T yysize = 0; - char *yymsg; - int yyx, yycount; - - yycount = 0; - /* Start YYX at -YYN if negative to avoid negative indexes in - YYCHECK. */ - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); yyx++) - if (yycheck[yyx + yyn] == yyx) - yysize += yystrlen (yytname[yyx]) + 15, yycount++; - yysize += yystrlen ("parse error, unexpected ") + 1; - yysize += yystrlen (yytname[YYTRANSLATE (yychar)]); - yymsg = (char *) YYSTACK_ALLOC (yysize); - if (yymsg != 0) - { - char *yyp = yystpcpy (yymsg, "parse error, unexpected "); - yyp = yystpcpy (yyp, yytname[YYTRANSLATE (yychar)]); - - if (yycount < 5) - { - yycount = 0; - for (yyx = yyn < 0 ? -yyn : 0; - yyx < (int) (sizeof (yytname) / sizeof (char *)); - yyx++) - if (yycheck[yyx + yyn] == yyx) - { - const char *yyq = ! yycount ? ", expecting " : " or "; - yyp = yystpcpy (yyp, yyq); - yyp = yystpcpy (yyp, yytname[yyx]); - yycount++; - } - } - yyerror (yymsg); - YYSTACK_FREE (yymsg); - } - else - yyerror ("parse error; also virtual memory exhausted"); - } - else -#endif /* defined (YYERROR_VERBOSE) */ - yyerror ("parse error"); +break; +#line 1834 "sudo.tab.c" } - goto yyerrlab1; - - -/*--------------------------------------------------. -| yyerrlab1 -- error raised explicitly by an action | -`--------------------------------------------------*/ -yyerrlab1: - if (yyerrstatus == 3) + yyssp -= yym; + yystate = *yyssp; + yyvsp -= yym; + yym = yylhs[yyn]; + if (yystate == 0 && yym == 0) { - /* If just tried and failed to reuse lookahead token after an - error, discard it. */ - - /* return failure if at end of input */ - if (yychar == YYEOF) - YYABORT; - YYDPRINTF ((stderr, "Discarding token %d (%s).\n", - yychar, yytname[yychar1])); - yychar = YYEMPTY; - } - - /* Else will try to reuse lookahead token after shifting the error - token. */ - - yyerrstatus = 3; /* Each real token shifted decrements this */ - - goto yyerrhandle; - - -/*-------------------------------------------------------------------. -| yyerrdefault -- current state does not do anything special for the | -| error token. | -`-------------------------------------------------------------------*/ -yyerrdefault: -#if 0 - /* This is wrong; only states that explicitly want error tokens - should shift them. */ - - /* If its default is to accept any token, ok. Otherwise pop it. */ - yyn = yydefact[yystate]; - if (yyn) - goto yydefault; -#endif - - -/*---------------------------------------------------------------. -| yyerrpop -- pop the current state because it cannot handle the | -| error token | -`---------------------------------------------------------------*/ -yyerrpop: - if (yyssp == yyss) - YYABORT; - yyvsp--; - yystate = *--yyssp; -#if YYLSP_NEEDED - yylsp--; +#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) - { - short *yyssp1 = yyss - 1; - YYFPRINTF (stderr, "Error: state stack now"); - while (yyssp1 != yyssp) - YYFPRINTF (stderr, " %d", *++yyssp1); - YYFPRINTF (stderr, "\n"); + 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 - -/*--------------. -| yyerrhandle. | -`--------------*/ -yyerrhandle: - yyn = yypact[yystate]; - if (yyn == YYFLAG) - goto yyerrdefault; - - yyn += YYTERROR; - if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) - goto yyerrdefault; - - yyn = yytable[yyn]; - if (yyn < 0) + if (yyssp >= yysslim && yygrowstack()) { - if (yyn == YYFLAG) - goto yyerrpop; - yyn = -yyn; - goto yyreduce; + goto yyoverflow; } - else if (yyn == 0) - goto yyerrpop; - - if (yyn == YYFINAL) - YYACCEPT; - - YYDPRINTF ((stderr, "Shifting error token, ")); - - *++yyvsp = yylval; -#if YYLSP_NEEDED - *++yylsp = yylloc; -#endif - - yystate = yyn; - goto yynewstate; - - -/*-------------------------------------. -| yyacceptlab -- YYACCEPT comes here. | -`-------------------------------------*/ -yyacceptlab: - yyresult = 0; - goto yyreturn; - -/*-----------------------------------. -| yyabortlab -- YYABORT comes here. | -`-----------------------------------*/ -yyabortlab: - yyresult = 1; - goto yyreturn; - -/*---------------------------------------------. -| yyoverflowab -- parser overflow comes here. | -`---------------------------------------------*/ -yyoverflowlab: - yyerror ("parser stack overflow"); - yyresult = 2; - /* Fall through. */ - -yyreturn: -#ifndef yyoverflow - if (yyss != yyssa) - YYSTACK_FREE (yyss); -#endif - return yyresult; -} -#line 839 "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() -{ - int i; - char *p; - struct generic_alias *ga, key; - - (void) printf("User %s may run the following commands on this host:\n", - user_name); - for (i = 0; i < cm_list_len; i++) { - - /* Print the runas list. */ - (void) fputs(" ", stdout); - if (cm_list[i].runas) { - (void) putchar('('); - p = strtok(cm_list[i].runas, ", "); - do { - if (p != cm_list[i].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_str(I_RUNAS_DEFAULT)); - } - - /* Is a password required? */ - if (cm_list[i].nopasswd == TRUE && def_flag(I_AUTHENTICATE)) - (void) fputs("NOPASSWD: ", stdout); - else if (cm_list[i].nopasswd == FALSE && !def_flag(I_AUTHENTICATE)) - (void) fputs("PASSWD: ", stdout); - - /* Print the actual command or expanded Cmnd_Alias. */ - key.alias = cm_list[i].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[i].cmnd); - } - - /* Be nice and free up space now that we are done. */ - for (i = 0; i < ga_list_len; i++) { - free(ga_list[i].alias); - free(ga_list[i].entries); - } - free(ga_list); - ga_list = NULL; - - for (i = 0; i < cm_list_len; i++) { - free(cm_list[i].runas); - free(cm_list[i].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_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. */ - dst += *dst_len; - *dst_len += src_len; - *dst = '\0'; - if (separator) - (void) strcat(dst, separator); - (void) strcat(dst, src); -} - -/* - * 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 *) - erealloc(ga_list, sizeof(struct generic_alias) * ga_list_size); - } - - 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 *) - erealloc(cm_list, sizeof(struct command_match) * cm_list_size); - } - - cm_list[cm_list_len].runas = cm_list[cm_list_len].cmnd = NULL; - cm_list[cm_list_len].nopasswd = FALSE; -} - -/* - * Frees up spaced used by a previous parser run and allocates new space - * for various data structures. - */ -void -init_parser() -{ - - /* Free up old data structures if we run the parser more than once. */ - if (match) { - free(match); - match = NULL; - top = 0; - parse_error = FALSE; - errorlineno = -1; - sudolineno = 1; - } - - /* Allocate space for the matching stack. */ - stacksize = STACKINCREMENT; - match = (struct matchstack *) emalloc(sizeof(struct matchstack) * stacksize); - - /* Allocate space for the match list (for `sudo -l'). */ - if (printmatches == TRUE) - expand_match_list(); + *++yyssp = yystate; + *++yyvsp = yyval; + goto yyloop; +yyoverflow: + yyerror("yacc stack overflow"); +yyabort: + return (1); +yyaccept: + return (0); } diff --git a/sudo.tab.h b/sudo.tab.h index b2afd8d..71b1255 100644 --- a/sudo.tab.h +++ b/sudo.tab.h @@ -1,38 +1,27 @@ -#ifndef BISON_SUDO_TAB_H -# define BISON_SUDO_TAB_H - -#ifndef YYSTYPE +#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 RUNAS 267 +#define NOPASSWD 268 +#define PASSWD 269 +#define ALL 270 +#define COMMENT 271 +#define HOSTALIAS 272 +#define CMNDALIAS 273 +#define USERALIAS 274 +#define RUNASALIAS 275 +#define ERROR 276 typedef union { char *string; int BOOLEAN; struct sudo_command command; int tok; -} yystype; -# define YYSTYPE yystype -# define YYSTYPE_IS_TRIVIAL 1 -#endif -# 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 RUNAS 267 -# define NOPASSWD 268 -# define PASSWD 269 -# define ALL 270 -# define COMMENT 271 -# define HOSTALIAS 272 -# define CMNDALIAS 273 -# define USERALIAS 274 -# define RUNASALIAS 275 -# define ERROR 276 - - +} YYSTYPE; extern YYSTYPE yylval; - -#endif /* not BISON_SUDO_TAB_H */ -- 2.47.2