Annotation of embedaddon/sudo/plugins/sudoers/toke.l, revision 1.1.1.4

1.1       misho       1: %{
                      2: /*
1.1.1.4 ! misho       3:  * Copyright (c) 1996, 1998-2005, 2007-2013
1.1       misho       4:  *     Todd C. Miller <Todd.Miller@courtesan.com>
                      5:  *
                      6:  * Permission to use, copy, modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     11:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     12:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     13:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     14:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     15:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     16:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     17:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     18:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     19:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     20:  *
                     21:  * Sponsored in part by the Defense Advanced Research Projects
                     22:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
                     23:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
                     24:  */
                     25: 
                     26: #include <config.h>
                     27: 
                     28: #include <sys/types.h>
                     29: #include <sys/stat.h>
                     30: #include <stdio.h>
                     31: #ifdef STDC_HEADERS
                     32: # include <stdlib.h>
                     33: # include <stddef.h>
                     34: #else
                     35: # ifdef HAVE_STDLIB_H
                     36: #  include <stdlib.h>
                     37: # endif
                     38: #endif /* STDC_HEADERS */
                     39: #ifdef HAVE_STRING_H
                     40: # include <string.h>
                     41: #endif /* HAVE_STRING_H */
                     42: #ifdef HAVE_STRINGS_H
                     43: # include <strings.h>
                     44: #endif /* HAVE_STRINGS_H */
1.1.1.4 ! misho      45: #if defined(HAVE_STDINT_H)
        !            46: # include <stdint.h>
        !            47: #elif defined(HAVE_INTTYPES_H)
        !            48: # include <inttypes.h>
        !            49: #endif
1.1       misho      50: #ifdef HAVE_UNISTD_H
                     51: # include <unistd.h>
                     52: #endif /* HAVE_UNISTD_H */
                     53: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
                     54: # include <malloc.h>
                     55: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
                     56: #ifdef HAVE_DIRENT_H
                     57: # include <dirent.h>
                     58: # define NAMLEN(dirent) strlen((dirent)->d_name)
                     59: #else
                     60: # define dirent direct
                     61: # define NAMLEN(dirent) (dirent)->d_namlen
                     62: # ifdef HAVE_SYS_NDIR_H
                     63: #  include <sys/ndir.h>
                     64: # endif
                     65: # ifdef HAVE_SYS_DIR_H
                     66: #  include <sys/dir.h>
                     67: # endif
                     68: # ifdef HAVE_NDIR_H
                     69: #  include <ndir.h>
                     70: # endif
                     71: #endif
                     72: #include <errno.h>
                     73: #include <ctype.h>
                     74: #include "sudoers.h"
                     75: #include "parse.h"
                     76: #include "toke.h"
                     77: #include <gram.h>
1.1.1.2   misho      78: #include "lbuf.h"
1.1.1.4 ! misho      79: #include "sha2.h"
1.1.1.2   misho      80: #include "secure_path.h"
1.1       misho      81: 
1.1.1.4 ! misho      82: extern YYSTYPE sudoerslval;
1.1.1.2   misho      83: extern bool parse_error;
                     84: extern bool sudoers_warnings;
1.1       misho      85: int sudolineno;
1.1.1.2   misho      86: int last_token;
1.1       misho      87: char *sudoers;
                     88: 
1.1.1.2   misho      89: /* Default sudoers path, mode and owner (may be set via sudo.conf) */
                     90: const char *sudoers_file = _PATH_SUDOERS;
                     91: mode_t sudoers_mode = SUDOERS_MODE;
                     92: uid_t sudoers_uid = SUDOERS_UID;
                     93: gid_t sudoers_gid = SUDOERS_GID;
1.1       misho      94: 
1.1.1.2   misho      95: static bool continued, sawspace;
                     96: static int prev_state;
1.1.1.4 ! misho      97: static int digest_len;
1.1.1.2   misho      98: 
                     99: static bool _push_include(char *, bool);
                    100: static bool pop_include(void);
1.1       misho     101: static char *parse_include(char *);
                    102: 
                    103: int (*trace_print)(const char *msg) = sudoers_trace_print;
                    104: 
1.1.1.2   misho     105: #define LEXRETURN(n)   do {    \
                    106:        last_token = (n);       \
                    107:        return (n);             \
                    108: } while (0)
                    109: 
1.1.1.4 ! misho     110: #define ECHO   ignore_result(fwrite(sudoerstext, sudoersleng, 1, sudoersout))
1.1.1.2   misho     111: 
                    112: #define        push_include(_p)        (_push_include((_p), false))
                    113: #define        push_includedir(_p)     (_push_include((_p), true))
1.1       misho     114: %}
                    115: 
                    116: HEX16                  [0-9A-Fa-f]{1,4}
                    117: OCTET                  (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
                    118: IPV4ADDR               {OCTET}(\.{OCTET}){3}
                    119: IPV6ADDR               ({HEX16}?:){2,7}{HEX16}?|({HEX16}?:){2,6}:{IPV4ADDR}
                    120: 
                    121: HOSTNAME               [[:alnum:]_-]+
                    122: WORD                   ([^#>!=:,\(\) \t\n\\\"]|\\[^\n])+
                    123: ID                     #-?[0-9]+
                    124: PATH                   \/(\\[\,:= \t#]|[^\,:=\\ \t\n#])+
                    125: ENVAR                  ([^#!=, \t\n\\\"]|\\[^\n])([^#=, \t\n\\\"]|\\[^\n])*
                    126: DEFVAR                 [a-z_]+
                    127: 
                    128: %option noinput
                    129: %option nounput
                    130: %option noyywrap
1.1.1.4 ! misho     131: %option prefix="sudoers"
1.1       misho     132: 
                    133: %s     GOTDEFS
                    134: %x     GOTCMND
                    135: %x     STARTDEFS
                    136: %x     INDEFS
                    137: %x     INSTR
1.1.1.4 ! misho     138: %s     WANTDIGEST
1.1       misho     139: 
                    140: %%
                    141: <GOTDEFS>[[:blank:]]*,[[:blank:]]* {
                    142:                            LEXTRACE(", ");
1.1.1.2   misho     143:                            LEXRETURN(',');
1.1       misho     144:                        }                       /* return ',' */
                    145: 
                    146: <GOTDEFS>[[:blank:]]+  BEGIN STARTDEFS;
                    147: 
                    148: <STARTDEFS>{DEFVAR}    {
                    149:                            BEGIN INDEFS;
                    150:                            LEXTRACE("DEFVAR ");
1.1.1.4 ! misho     151:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     152:                                yyterminate();
1.1.1.2   misho     153:                            LEXRETURN(DEFVAR);
1.1       misho     154:                        }
                    155: 
                    156: <INDEFS>{
                    157:     ,                  {
                    158:                            BEGIN STARTDEFS;
                    159:                            LEXTRACE(", ");
1.1.1.2   misho     160:                            LEXRETURN(',');
1.1       misho     161:                        }                       /* return ',' */
                    162: 
                    163:     =                  {
                    164:                            LEXTRACE("= ");
1.1.1.2   misho     165:                            LEXRETURN('=');
1.1       misho     166:                        }                       /* return '=' */
                    167: 
                    168:     \+=                        {
                    169:                            LEXTRACE("+= ");
1.1.1.2   misho     170:                            LEXRETURN('+');
1.1       misho     171:                        }                       /* return '+' */
                    172: 
                    173:     -=                 {
                    174:                            LEXTRACE("-= ");
1.1.1.2   misho     175:                            LEXRETURN('-');
1.1       misho     176:                        }                       /* return '-' */
                    177: 
                    178:     \"                 {
                    179:                            LEXTRACE("BEGINSTR ");
1.1.1.4 ! misho     180:                            sudoerslval.string = NULL;
1.1       misho     181:                            prev_state = YY_START;
                    182:                            BEGIN INSTR;
                    183:                        }
                    184: 
                    185:     {ENVAR}            {
                    186:                            LEXTRACE("WORD(2) ");
1.1.1.4 ! misho     187:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     188:                                yyterminate();
1.1.1.2   misho     189:                            LEXRETURN(WORD);
1.1       misho     190:                        }
                    191: }
                    192: 
                    193: <INSTR>{
                    194:     \\[[:blank:]]*\n[[:blank:]]*       {
                    195:                            /* Line continuation char followed by newline. */
1.1.1.2   misho     196:                            sudolineno++;
                    197:                            continued = true;
1.1       misho     198:                        }
                    199: 
                    200:     \"                 {
                    201:                            LEXTRACE("ENDSTR ");
                    202:                            BEGIN prev_state;
                    203: 
1.1.1.4 ! misho     204:                            if (sudoerslval.string == NULL) {
1.1       misho     205:                                LEXTRACE("ERROR "); /* empty string */
1.1.1.2   misho     206:                                LEXRETURN(ERROR);
1.1       misho     207:                            }
                    208:                            if (prev_state == INITIAL) {
1.1.1.4 ! misho     209:                                switch (sudoerslval.string[0]) {
1.1       misho     210:                                case '%':
1.1.1.4 ! misho     211:                                    if (sudoerslval.string[1] == '\0' ||
        !           212:                                        (sudoerslval.string[1] == ':' &&
        !           213:                                        sudoerslval.string[2] == '\0')) {
1.1       misho     214:                                        LEXTRACE("ERROR "); /* empty group */
1.1.1.2   misho     215:                                        LEXRETURN(ERROR);
1.1       misho     216:                                    }
                    217:                                    LEXTRACE("USERGROUP ");
1.1.1.2   misho     218:                                    LEXRETURN(USERGROUP);
1.1       misho     219:                                case '+':
1.1.1.4 ! misho     220:                                    if (sudoerslval.string[1] == '\0') {
1.1       misho     221:                                        LEXTRACE("ERROR "); /* empty netgroup */
1.1.1.2   misho     222:                                        LEXRETURN(ERROR);
1.1       misho     223:                                    }
                    224:                                    LEXTRACE("NETGROUP ");
1.1.1.2   misho     225:                                    LEXRETURN(NETGROUP);
1.1       misho     226:                                }
                    227:                            }
                    228:                            LEXTRACE("WORD(4) ");
1.1.1.2   misho     229:                            LEXRETURN(WORD);
1.1       misho     230:                        }
                    231: 
                    232:     \\                 {
                    233:                            LEXTRACE("BACKSLASH ");
1.1.1.4 ! misho     234:                            if (!append(sudoerstext, sudoersleng))
1.1       misho     235:                                yyterminate();
                    236:                        }
                    237: 
                    238:     ([^\"\n\\]|\\\")+  {
                    239:                            LEXTRACE("STRBODY ");
1.1.1.4 ! misho     240:                            if (!append(sudoerstext, sudoersleng))
1.1       misho     241:                                yyterminate();
                    242:                        }
                    243: }
                    244: 
                    245: <GOTCMND>{
                    246:     \\[\*\?\[\]\!]     {
                    247:                            /* quoted fnmatch glob char, pass verbatim */
                    248:                            LEXTRACE("QUOTEDCHAR ");
1.1.1.4 ! misho     249:                            if (!fill_args(sudoerstext, 2, sawspace))
1.1       misho     250:                                yyterminate();
1.1.1.2   misho     251:                            sawspace = false;
1.1       misho     252:                        }
                    253: 
                    254:     \\[:\\,= \t#]      {
                    255:                            /* quoted sudoers special char, strip backslash */
                    256:                            LEXTRACE("QUOTEDCHAR ");
1.1.1.4 ! misho     257:                            if (!fill_args(sudoerstext + 1, 1, sawspace))
1.1       misho     258:                                yyterminate();
1.1.1.2   misho     259:                            sawspace = false;
1.1       misho     260:                        }
                    261: 
                    262:     [#:\,=\n]          {
                    263:                            BEGIN INITIAL;
                    264:                            yyless(0);
1.1.1.2   misho     265:                            LEXRETURN(COMMAND);
1.1       misho     266:                        }                       /* end of command line args */
                    267: 
                    268:     [^#\\:, \t\n]+     {
                    269:                            LEXTRACE("ARG ");
1.1.1.4 ! misho     270:                            if (!fill_args(sudoerstext, sudoersleng, sawspace))
1.1       misho     271:                                yyterminate();
1.1.1.2   misho     272:                            sawspace = false;
1.1       misho     273:                        }                       /* a command line arg */
                    274: }
                    275: 
1.1.1.4 ! misho     276: <WANTDIGEST>[[:xdigit:]]+ {
        !           277:                            /* Only return DIGEST if the length is correct. */
        !           278:                            if (sudoersleng == digest_len * 2) {
        !           279:                                if (!fill(sudoerstext, sudoersleng))
        !           280:                                    yyterminate();
        !           281:                                BEGIN INITIAL;
        !           282:                                LEXTRACE("DIGEST ");
        !           283:                                LEXRETURN(DIGEST);
        !           284:                            }
        !           285:                            BEGIN INITIAL;
        !           286:                            yyless(sudoersleng);
        !           287:                        } /* hex digest */
        !           288: 
        !           289: <WANTDIGEST>[A-Za-z0-9\+/=]+ {
        !           290:                            /* Only return DIGEST if the length is correct. */
        !           291:                            size_t len;
        !           292:                            if (sudoerstext[sudoersleng - 1] == '=') {
        !           293:                                /* use padding */
        !           294:                                len = 4 * ((digest_len + 2) / 3);
        !           295:                            } else {
        !           296:                                /* no padding */
        !           297:                                len = (4 * digest_len + 2) / 3;
        !           298:                            }
        !           299:                            if (sudoersleng == len) {
        !           300:                                if (!fill(sudoerstext, sudoersleng))
        !           301:                                    yyterminate();
        !           302:                                BEGIN INITIAL;
        !           303:                                LEXTRACE("DIGEST ");
        !           304:                                LEXRETURN(DIGEST);
        !           305:                            }
        !           306:                            BEGIN INITIAL;
        !           307:                            yyless(sudoersleng);
        !           308:                        } /* base64 digest */
        !           309: 
1.1.1.2   misho     310: <INITIAL>^#include[[:blank:]]+.*\n {
1.1       misho     311:                            char *path;
                    312: 
                    313:                            if (continued) {
                    314:                                LEXTRACE("ERROR ");
1.1.1.2   misho     315:                                LEXRETURN(ERROR);
1.1       misho     316:                            }
                    317: 
1.1.1.4 ! misho     318:                            if ((path = parse_include(sudoerstext)) == NULL)
1.1       misho     319:                                yyterminate();
                    320: 
                    321:                            LEXTRACE("INCLUDE\n");
                    322: 
                    323:                            /* Push current buffer and switch to include file */
                    324:                            if (!push_include(path))
                    325:                                yyterminate();
                    326:                        }
                    327: 
1.1.1.2   misho     328: <INITIAL>^#includedir[[:blank:]]+.*\n {
1.1       misho     329:                            char *path;
                    330: 
                    331:                            if (continued) {
                    332:                                LEXTRACE("ERROR ");
1.1.1.2   misho     333:                                LEXRETURN(ERROR);
1.1       misho     334:                            }
                    335: 
1.1.1.4 ! misho     336:                            if ((path = parse_include(sudoerstext)) == NULL)
1.1       misho     337:                                yyterminate();
                    338: 
                    339:                            LEXTRACE("INCLUDEDIR\n");
                    340: 
                    341:                            /*
                    342:                             * Push current buffer and switch to include file.
                    343:                             * We simply ignore empty directories.
                    344:                             */
                    345:                            if (!push_includedir(path) && parse_error)
                    346:                                yyterminate();
                    347:                        }
                    348: 
                    349: <INITIAL>^[[:blank:]]*Defaults([:@>\!][[:blank:]]*\!*\"?({ID}|{WORD}))? {
                    350:                            char deftype;
                    351:                            int n;
                    352: 
                    353:                            if (continued) {
                    354:                                LEXTRACE("ERROR ");
1.1.1.2   misho     355:                                LEXRETURN(ERROR);
1.1       misho     356:                            }
                    357: 
1.1.1.4 ! misho     358:                            for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
1.1       misho     359:                                continue;
                    360:                            n += sizeof("Defaults") - 1;
1.1.1.4 ! misho     361:                            if ((deftype = sudoerstext[n++]) != '\0') {
        !           362:                                while (isblank((unsigned char)sudoerstext[n]))
1.1       misho     363:                                    n++;
                    364:                            }
                    365:                            BEGIN GOTDEFS;
                    366:                            switch (deftype) {
                    367:                                case ':':
                    368:                                    yyless(n);
                    369:                                    LEXTRACE("DEFAULTS_USER ");
1.1.1.2   misho     370:                                    LEXRETURN(DEFAULTS_USER);
1.1       misho     371:                                case '>':
                    372:                                    yyless(n);
                    373:                                    LEXTRACE("DEFAULTS_RUNAS ");
1.1.1.2   misho     374:                                    LEXRETURN(DEFAULTS_RUNAS);
1.1       misho     375:                                case '@':
                    376:                                    yyless(n);
                    377:                                    LEXTRACE("DEFAULTS_HOST ");
1.1.1.2   misho     378:                                    LEXRETURN(DEFAULTS_HOST);
1.1       misho     379:                                case '!':
                    380:                                    yyless(n);
                    381:                                    LEXTRACE("DEFAULTS_CMND ");
1.1.1.2   misho     382:                                    LEXRETURN(DEFAULTS_CMND);
1.1       misho     383:                                default:
                    384:                                    LEXTRACE("DEFAULTS ");
1.1.1.2   misho     385:                                    LEXRETURN(DEFAULTS);
1.1       misho     386:                            }
                    387:                        }
                    388: 
                    389: <INITIAL>^[[:blank:]]*(Host|Cmnd|User|Runas)_Alias     {
                    390:                            int n;
                    391: 
                    392:                            if (continued) {
                    393:                                LEXTRACE("ERROR ");
1.1.1.2   misho     394:                                LEXRETURN(ERROR);
1.1       misho     395:                            }
                    396: 
1.1.1.4 ! misho     397:                            for (n = 0; isblank((unsigned char)sudoerstext[n]); n++)
1.1       misho     398:                                continue;
1.1.1.4 ! misho     399:                            switch (sudoerstext[n]) {
1.1       misho     400:                                case 'H':
                    401:                                    LEXTRACE("HOSTALIAS ");
1.1.1.2   misho     402:                                    LEXRETURN(HOSTALIAS);
1.1       misho     403:                                case 'C':
                    404:                                    LEXTRACE("CMNDALIAS ");
1.1.1.2   misho     405:                                    LEXRETURN(CMNDALIAS);
1.1       misho     406:                                case 'U':
                    407:                                    LEXTRACE("USERALIAS ");
1.1.1.2   misho     408:                                    LEXRETURN(USERALIAS);
1.1       misho     409:                                case 'R':
                    410:                                    LEXTRACE("RUNASALIAS ");
1.1.1.2   misho     411:                                    LEXRETURN(RUNASALIAS);
1.1       misho     412:                            }
                    413:                        }
                    414: 
                    415: NOPASSWD[[:blank:]]*:  {
                    416:                                /* cmnd does not require passwd for this user */
                    417:                                LEXTRACE("NOPASSWD ");
1.1.1.2   misho     418:                                LEXRETURN(NOPASSWD);
1.1       misho     419:                        }
                    420: 
                    421: PASSWD[[:blank:]]*:    {
                    422:                                /* cmnd requires passwd for this user */
                    423:                                LEXTRACE("PASSWD ");
1.1.1.2   misho     424:                                LEXRETURN(PASSWD);
1.1       misho     425:                        }
                    426: 
                    427: NOEXEC[[:blank:]]*:    {
                    428:                                LEXTRACE("NOEXEC ");
1.1.1.2   misho     429:                                LEXRETURN(NOEXEC);
1.1       misho     430:                        }
                    431: 
                    432: EXEC[[:blank:]]*:      {
                    433:                                LEXTRACE("EXEC ");
1.1.1.2   misho     434:                                LEXRETURN(EXEC);
1.1       misho     435:                        }
                    436: 
                    437: SETENV[[:blank:]]*:    {
                    438:                                LEXTRACE("SETENV ");
1.1.1.2   misho     439:                                LEXRETURN(SETENV);
1.1       misho     440:                        }
                    441: 
                    442: NOSETENV[[:blank:]]*:  {
                    443:                                LEXTRACE("NOSETENV ");
1.1.1.2   misho     444:                                LEXRETURN(NOSETENV);
1.1       misho     445:                        }
                    446: 
                    447: LOG_OUTPUT[[:blank:]]*:        {
                    448:                                LEXTRACE("LOG_OUTPUT ");
1.1.1.2   misho     449:                                LEXRETURN(LOG_OUTPUT);
1.1       misho     450:                        }
                    451: 
                    452: NOLOG_OUTPUT[[:blank:]]*:      {
                    453:                                LEXTRACE("NOLOG_OUTPUT ");
1.1.1.2   misho     454:                                LEXRETURN(NOLOG_OUTPUT);
1.1       misho     455:                        }
                    456: 
                    457: LOG_INPUT[[:blank:]]*: {
                    458:                                LEXTRACE("LOG_INPUT ");
1.1.1.2   misho     459:                                LEXRETURN(LOG_INPUT);
1.1       misho     460:                        }
                    461: 
                    462: NOLOG_INPUT[[:blank:]]*:       {
                    463:                                LEXTRACE("NOLOG_INPUT ");
1.1.1.2   misho     464:                                LEXRETURN(NOLOG_INPUT);
1.1       misho     465:                        }
                    466: 
                    467: <INITIAL,GOTDEFS>(\+|\%|\%:) {
                    468:                            /* empty group or netgroup */
                    469:                            LEXTRACE("ERROR ");
1.1.1.2   misho     470:                            LEXRETURN(ERROR);
1.1       misho     471:                        }
                    472: 
                    473: \+{WORD}               {
                    474:                            /* netgroup */
1.1.1.4 ! misho     475:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     476:                                yyterminate();
                    477:                            LEXTRACE("NETGROUP ");
1.1.1.2   misho     478:                            LEXRETURN(NETGROUP);
1.1       misho     479:                        }
                    480: 
                    481: \%:?({WORD}|{ID})      {
                    482:                            /* group */
1.1.1.4 ! misho     483:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     484:                                yyterminate();
                    485:                            LEXTRACE("USERGROUP ");
1.1.1.2   misho     486:                            LEXRETURN(USERGROUP);
1.1       misho     487:                        }
                    488: 
                    489: {IPV4ADDR}(\/{IPV4ADDR})? {
1.1.1.4 ! misho     490:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     491:                                yyterminate();
                    492:                            LEXTRACE("NTWKADDR ");
1.1.1.2   misho     493:                            LEXRETURN(NTWKADDR);
1.1       misho     494:                        }
                    495: 
                    496: {IPV4ADDR}\/([12]?[0-9]|3[0-2]) {
1.1.1.4 ! misho     497:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     498:                                yyterminate();
                    499:                            LEXTRACE("NTWKADDR ");
1.1.1.2   misho     500:                            LEXRETURN(NTWKADDR);
1.1       misho     501:                        }
                    502: 
                    503: {IPV6ADDR}(\/{IPV6ADDR})? {
1.1.1.4 ! misho     504:                            if (!ipv6_valid(sudoerstext)) {
1.1       misho     505:                                LEXTRACE("ERROR ");
1.1.1.2   misho     506:                                LEXRETURN(ERROR);
1.1       misho     507:                            }
1.1.1.4 ! misho     508:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     509:                                yyterminate();
                    510:                            LEXTRACE("NTWKADDR ");
1.1.1.2   misho     511:                            LEXRETURN(NTWKADDR);
1.1       misho     512:                        }
                    513: 
                    514: {IPV6ADDR}\/([0-9]|[1-9][0-9]|1[01][0-9]|12[0-8]) {
1.1.1.4 ! misho     515:                            if (!ipv6_valid(sudoerstext)) {
1.1       misho     516:                                LEXTRACE("ERROR ");
1.1.1.2   misho     517:                                LEXRETURN(ERROR);
1.1       misho     518:                            }
1.1.1.4 ! misho     519:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     520:                                yyterminate();
                    521:                            LEXTRACE("NTWKADDR ");
1.1.1.2   misho     522:                            LEXRETURN(NTWKADDR);
1.1       misho     523:                        }
                    524: 
                    525: ALL {
                    526:                            LEXTRACE("ALL ");
1.1.1.2   misho     527:                            LEXRETURN(ALL);
1.1       misho     528: 
                    529:                        }
                    530: 
                    531: <INITIAL>ROLE {
                    532: #ifdef HAVE_SELINUX
                    533:                            LEXTRACE("ROLE ");
1.1.1.2   misho     534:                            LEXRETURN(ROLE);
1.1       misho     535: #else
                    536:                            goto got_alias;
                    537: #endif
                    538:                        }
                    539: 
                    540: <INITIAL>TYPE {
                    541: #ifdef HAVE_SELINUX
                    542:                            LEXTRACE("TYPE ");
1.1.1.2   misho     543:                            LEXRETURN(TYPE);
1.1       misho     544: #else
                    545:                            goto got_alias;
                    546: #endif
                    547:                        }
1.1.1.3   misho     548: <INITIAL>PRIVS {
                    549: #ifdef HAVE_PRIV_SET
                    550:                            LEXTRACE("PRIVS ");
                    551:                            LEXRETURN(PRIVS);
                    552: #else
                    553:                            goto got_alias;
                    554: #endif
                    555:                        }
                    556: 
                    557: <INITIAL>LIMITPRIVS {
                    558: #ifdef HAVE_PRIV_SET
                    559:                            LEXTRACE("LIMITPRIVS ");
                    560:                            LEXRETURN(LIMITPRIVS);
                    561: #else
                    562:                            goto got_alias;
                    563: #endif
                    564:                        }
1.1       misho     565: 
                    566: [[:upper:]][[:upper:][:digit:]_]* {
                    567:                        got_alias:
1.1.1.4 ! misho     568:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     569:                                yyterminate();
                    570:                            LEXTRACE("ALIAS ");
1.1.1.2   misho     571:                            LEXRETURN(ALIAS);
1.1       misho     572:                        }
                    573: 
                    574: <GOTDEFS>({PATH}|sudoedit) {
1.1.1.4 ! misho     575:                            /* XXX - no way to specify digest for command */
1.1       misho     576:                            /* no command args allowed for Defaults!/path */
1.1.1.4 ! misho     577:                            if (!fill_cmnd(sudoerstext, sudoersleng))
1.1       misho     578:                                yyterminate();
                    579:                            LEXTRACE("COMMAND ");
1.1.1.2   misho     580:                            LEXRETURN(COMMAND);
1.1       misho     581:                        }
                    582: 
1.1.1.4 ! misho     583: sha224                 {
        !           584:                            digest_len = SHA224_DIGEST_LENGTH;
        !           585:                            BEGIN WANTDIGEST;
        !           586:                            LEXTRACE("SHA224 ");
        !           587:                            LEXRETURN(SHA224);
        !           588:                        }
        !           589: 
        !           590: sha256                 {
        !           591:                            digest_len = SHA256_DIGEST_LENGTH;
        !           592:                            BEGIN WANTDIGEST;
        !           593:                            LEXTRACE("SHA256 ");
        !           594:                            LEXRETURN(SHA256);
        !           595:                        }
        !           596: 
        !           597: sha384                 {
        !           598:                            digest_len = SHA384_DIGEST_LENGTH;
        !           599:                            BEGIN WANTDIGEST;
        !           600:                            LEXTRACE("SHA384 ");
        !           601:                            LEXRETURN(SHA384);
        !           602:                        }
        !           603: 
        !           604: sha512                 {
        !           605:                            digest_len = SHA512_DIGEST_LENGTH;
        !           606:                            BEGIN WANTDIGEST;
        !           607:                            LEXTRACE("SHA512 ");
        !           608:                            LEXRETURN(SHA512);
        !           609:                        }
        !           610: 
1.1       misho     611: sudoedit               {
                    612:                            BEGIN GOTCMND;
                    613:                            LEXTRACE("COMMAND ");
1.1.1.4 ! misho     614:                            if (!fill_cmnd(sudoerstext, sudoersleng))
1.1       misho     615:                                yyterminate();
                    616:                        }                       /* sudo -e */
                    617: 
                    618: {PATH}                 {
                    619:                            /* directories can't have args... */
1.1.1.4 ! misho     620:                            if (sudoerstext[sudoersleng - 1] == '/') {
1.1       misho     621:                                LEXTRACE("COMMAND ");
1.1.1.4 ! misho     622:                                if (!fill_cmnd(sudoerstext, sudoersleng))
1.1       misho     623:                                    yyterminate();
1.1.1.2   misho     624:                                LEXRETURN(COMMAND);
1.1       misho     625:                            } else {
                    626:                                BEGIN GOTCMND;
                    627:                                LEXTRACE("COMMAND ");
1.1.1.4 ! misho     628:                                if (!fill_cmnd(sudoerstext, sudoersleng))
1.1       misho     629:                                    yyterminate();
                    630:                            }
                    631:                        }                       /* a pathname */
                    632: 
                    633: <INITIAL,GOTDEFS>\" {
                    634:                            LEXTRACE("BEGINSTR ");
1.1.1.4 ! misho     635:                            sudoerslval.string = NULL;
1.1       misho     636:                            prev_state = YY_START;
                    637:                            BEGIN INSTR;
                    638:                        }
                    639: 
                    640: <INITIAL,GOTDEFS>({ID}|{WORD}) {
                    641:                            /* a word */
1.1.1.4 ! misho     642:                            if (!fill(sudoerstext, sudoersleng))
1.1       misho     643:                                yyterminate();
                    644:                            LEXTRACE("WORD(5) ");
1.1.1.2   misho     645:                            LEXRETURN(WORD);
1.1       misho     646:                        }
                    647: 
                    648: \(                     {
                    649:                            LEXTRACE("( ");
1.1.1.2   misho     650:                            LEXRETURN('(');
1.1       misho     651:                        }
                    652: 
                    653: \)                     {
                    654:                            LEXTRACE(") ");
1.1.1.2   misho     655:                            LEXRETURN(')');
1.1       misho     656:                        }
                    657: 
                    658: ,                      {
                    659:                            LEXTRACE(", ");
1.1.1.2   misho     660:                            LEXRETURN(',');
1.1       misho     661:                        }                       /* return ',' */
                    662: 
                    663: =                      {
                    664:                            LEXTRACE("= ");
1.1.1.2   misho     665:                            LEXRETURN('=');
1.1       misho     666:                        }                       /* return '=' */
                    667: 
                    668: :                      {
                    669:                            LEXTRACE(": ");
1.1.1.2   misho     670:                            LEXRETURN(':');
1.1       misho     671:                        }                       /* return ':' */
                    672: 
                    673: <*>!+                  {
1.1.1.4 ! misho     674:                            if (sudoersleng & 1) {
1.1       misho     675:                                LEXTRACE("!");
1.1.1.2   misho     676:                                LEXRETURN('!'); /* return '!' */
1.1       misho     677:                            }
                    678:                        }
                    679: 
                    680: <*>\n                  {
                    681:                            if (YY_START == INSTR) {
                    682:                                LEXTRACE("ERROR ");
1.1.1.2   misho     683:                                LEXRETURN(ERROR);       /* line break in string */
1.1       misho     684:                            }
                    685:                            BEGIN INITIAL;
1.1.1.2   misho     686:                            sudolineno++;
                    687:                            continued = false;
1.1       misho     688:                            LEXTRACE("\n");
1.1.1.2   misho     689:                            LEXRETURN(COMMENT);
1.1       misho     690:                        }                       /* return newline */
                    691: 
                    692: <*>[[:blank:]]+                {                       /* throw away space/tabs */
1.1.1.2   misho     693:                            sawspace = true;    /* but remember for fill_args */
1.1       misho     694:                        }
                    695: 
                    696: <*>\\[[:blank:]]*\n    {
1.1.1.2   misho     697:                            sawspace = true;    /* remember for fill_args */
                    698:                            sudolineno++;
                    699:                            continued = true;
1.1       misho     700:                        }                       /* throw away EOL after \ */
                    701: 
                    702: <INITIAL,STARTDEFS,INDEFS>#(-[^\n0-9].*|[^\n0-9-].*)?\n        {
                    703:                            BEGIN INITIAL;
1.1.1.2   misho     704:                            sudolineno++;
                    705:                            continued = false;
1.1       misho     706:                            LEXTRACE("#\n");
1.1.1.2   misho     707:                            LEXRETURN(COMMENT);
1.1       misho     708:                        }                       /* comment, not uid/gid */
                    709: 
                    710: <*>.                   {
                    711:                            LEXTRACE("ERROR ");
1.1.1.2   misho     712:                            LEXRETURN(ERROR);
1.1       misho     713:                        }       /* parse error */
                    714: 
                    715: <*><<EOF>>             {
                    716:                            if (YY_START != INITIAL) {
                    717:                                BEGIN INITIAL;
                    718:                                LEXTRACE("ERROR ");
1.1.1.2   misho     719:                                LEXRETURN(ERROR);
1.1       misho     720:                            }
                    721:                            if (!pop_include())
                    722:                                yyterminate();
                    723:                        }
                    724: 
                    725: %%
                    726: struct path_list {
                    727:     char *path;
                    728:     struct path_list *next;
                    729: };
                    730: 
                    731: struct include_stack {
                    732:     YY_BUFFER_STATE bs;
                    733:     char *path;
                    734:     struct path_list *more; /* more files in case of includedir */
                    735:     int lineno;
1.1.1.2   misho     736:     bool keepopen;
1.1       misho     737: };
                    738: 
                    739: static int
                    740: pl_compare(const void *v1, const void *v2)
                    741: {
                    742:     const struct path_list * const *p1 = v1;
                    743:     const struct path_list * const *p2 = v2;
                    744: 
                    745:     return strcmp((*p1)->path, (*p2)->path);
                    746: }
                    747: 
                    748: static char *
                    749: switch_dir(struct include_stack *stack, char *dirpath)
                    750: {
                    751:     DIR *dir;
                    752:     int i, count = 0;
                    753:     char *path = NULL;
                    754:     struct dirent *dent;
                    755:     struct stat sb;
                    756:     struct path_list *pl, *first = NULL;
                    757:     struct path_list **sorted = NULL;
1.1.1.2   misho     758:     debug_decl(switch_dir, SUDO_DEBUG_PARSER)
1.1       misho     759: 
                    760:     if (!(dir = opendir(dirpath))) {
                    761:        if (errno != ENOENT) {
1.1.1.4 ! misho     762:            warning("%s", dirpath);
        !           763:            sudoerserror(NULL);
1.1       misho     764:        }
                    765:        goto done;
                    766:     }
                    767:     while ((dent = readdir(dir))) {
                    768:        /* Ignore files that end in '~' or have a '.' in them. */
                    769:        if (dent->d_name[0] == '\0' || dent->d_name[NAMLEN(dent) - 1] == '~'
                    770:            || strchr(dent->d_name, '.') != NULL) {
                    771:            continue;
                    772:        }
                    773:        if (asprintf(&path, "%s/%s", dirpath, dent->d_name) == -1) {
                    774:            closedir(dir);
                    775:            goto bad;
                    776:        }
                    777:        if (stat(path, &sb) != 0 || !S_ISREG(sb.st_mode)) {
                    778:            efree(path);
                    779:            path = NULL;
                    780:            continue;
                    781:        }
                    782:        pl = malloc(sizeof(*pl));
                    783:        if (pl == NULL)
                    784:            goto bad;
                    785:        pl->path = path;
                    786:        pl->next = first;
                    787:        first = pl;
1.1.1.4 ! misho     788:        path = NULL;
1.1       misho     789:        count++;
                    790:     }
                    791:     closedir(dir);
                    792: 
                    793:     if (count == 0)
                    794:        goto done;
                    795: 
                    796:     /* Sort the list as an array. */
                    797:     sorted = malloc(sizeof(*sorted) * count);
                    798:     if (sorted == NULL)
                    799:        goto bad;
                    800:     pl = first;
                    801:     for (i = 0; i < count; i++) {
                    802:        sorted[i] = pl;
                    803:        pl = pl->next;
                    804:     }
                    805:     qsort(sorted, count, sizeof(*sorted), pl_compare);
                    806: 
                    807:     /* Apply sorting to the list. */
                    808:     first = sorted[0];
                    809:     sorted[count - 1]->next = NULL;
                    810:     for (i = 1; i < count; i++)
                    811:        sorted[i - 1]->next = sorted[i];
                    812:     efree(sorted);
                    813: 
                    814:     /* Pull out the first element for parsing, leave the rest for later. */
                    815:     if (count) {
                    816:        path = first->path;
                    817:        pl = first->next;
                    818:        efree(first);
                    819:        stack->more = pl;
                    820:     } else {
                    821:        path = NULL;
                    822:     }
                    823: done:
                    824:     efree(dirpath);
1.1.1.2   misho     825:     debug_return_str(path);
1.1       misho     826: bad:
                    827:     while (first != NULL) {
                    828:        pl = first;
                    829:        first = pl->next;
1.1.1.4 ! misho     830:        efree(pl->path);
        !           831:        efree(pl);
1.1       misho     832:     }
                    833:     efree(sorted);
                    834:     efree(dirpath);
                    835:     efree(path);
1.1.1.2   misho     836:     debug_return_str(NULL);
1.1       misho     837: }
                    838: 
                    839: #define MAX_SUDOERS_DEPTH      128
                    840: #define SUDOERS_STACK_INCREMENT        16
                    841: 
                    842: static size_t istacksize, idepth;
                    843: static struct include_stack *istack;
1.1.1.2   misho     844: static bool keepopen;
1.1       misho     845: 
                    846: void
                    847: init_lexer(void)
                    848: {
                    849:     struct path_list *pl;
1.1.1.2   misho     850:     debug_decl(init_lexer, SUDO_DEBUG_PARSER)
1.1       misho     851: 
                    852:     while (idepth) {
                    853:        idepth--;
                    854:        while ((pl = istack[idepth].more) != NULL) {
                    855:            istack[idepth].more = pl->next;
                    856:            efree(pl->path);
                    857:            efree(pl);
                    858:        }
                    859:        efree(istack[idepth].path);
                    860:        if (idepth && !istack[idepth].keepopen)
                    861:            fclose(istack[idepth].bs->yy_input_file);
1.1.1.4 ! misho     862:        sudoers_delete_buffer(istack[idepth].bs);
1.1       misho     863:     }
                    864:     efree(istack);
                    865:     istack = NULL;
                    866:     istacksize = idepth = 0;
                    867:     sudolineno = 1;
1.1.1.2   misho     868:     keepopen = false;
                    869:     sawspace = false;
                    870:     continued = false;
1.1       misho     871:     prev_state = INITIAL;
1.1.1.2   misho     872: 
                    873:     debug_return;
1.1       misho     874: }
                    875: 
1.1.1.2   misho     876: static bool
                    877: _push_include(char *path, bool isdir)
1.1       misho     878: {
                    879:     struct path_list *pl;
                    880:     FILE *fp;
1.1.1.2   misho     881:     debug_decl(_push_include, SUDO_DEBUG_PARSER)
1.1       misho     882: 
                    883:     /* push current state onto stack */
                    884:     if (idepth >= istacksize) {
                    885:        if (idepth > MAX_SUDOERS_DEPTH) {
1.1.1.4 ! misho     886:            sudoerserror(N_("too many levels of includes"));
1.1.1.2   misho     887:            debug_return_bool(false);
1.1       misho     888:        }
                    889:        istacksize += SUDOERS_STACK_INCREMENT;
                    890:        istack = (struct include_stack *) realloc(istack,
                    891:            sizeof(*istack) * istacksize);
                    892:        if (istack == NULL) {
1.1.1.4 ! misho     893:            warning(NULL);
        !           894:            sudoerserror(NULL);
1.1.1.2   misho     895:            debug_return_bool(false);
1.1       misho     896:        }
                    897:     }
                    898:     if (isdir) {
1.1.1.2   misho     899:        struct stat sb;
                    900:        switch (sudo_secure_dir(path, sudoers_uid, sudoers_gid, &sb)) {
                    901:            case SUDO_PATH_SECURE:
                    902:                break;
                    903:            case SUDO_PATH_MISSING:
                    904:                debug_return_bool(false);
                    905:            case SUDO_PATH_BAD_TYPE:
                    906:                errno = ENOTDIR;
                    907:                if (sudoers_warnings) {
                    908:                    warning("%s", path);
                    909:                }
                    910:                debug_return_bool(false);
                    911:            case SUDO_PATH_WRONG_OWNER:
                    912:                if (sudoers_warnings) {
                    913:                    warningx(_("%s is owned by uid %u, should be %u"),   
                    914:                        path, (unsigned int) sb.st_uid,
                    915:                        (unsigned int) sudoers_uid);
                    916:                }
                    917:                debug_return_bool(false);
                    918:            case SUDO_PATH_WORLD_WRITABLE:
                    919:                if (sudoers_warnings) {
                    920:                    warningx(_("%s is world writable"), path);
                    921:                }
                    922:                debug_return_bool(false);
                    923:            case SUDO_PATH_GROUP_WRITABLE:
                    924:                if (sudoers_warnings) {
                    925:                    warningx(_("%s is owned by gid %u, should be %u"),
                    926:                        path, (unsigned int) sb.st_gid,
                    927:                        (unsigned int) sudoers_gid);
                    928:                }
                    929:                debug_return_bool(false);
                    930:            default:
                    931:                /* NOTREACHED */
                    932:                debug_return_bool(false);
                    933:        }
1.1       misho     934:        if (!(path = switch_dir(&istack[idepth], path))) {
1.1.1.4 ! misho     935:            /* switch_dir() called sudoerserror() for us */
1.1.1.2   misho     936:            debug_return_bool(false);
1.1       misho     937:        }
1.1.1.2   misho     938:        while ((fp = open_sudoers(path, false, &keepopen)) == NULL) {
1.1       misho     939:            /* Unable to open path in includedir, go to next one, if any. */
                    940:            efree(path);
                    941:            if ((pl = istack[idepth].more) == NULL)
1.1.1.2   misho     942:                debug_return_bool(false);
1.1       misho     943:            path = pl->path;
                    944:            istack[idepth].more = pl->next;
                    945:            efree(pl);
                    946:        }
                    947:     } else {
1.1.1.2   misho     948:        if ((fp = open_sudoers(path, true, &keepopen)) == NULL) {
1.1.1.3   misho     949:            /* The error was already printed by open_sudoers() */
1.1.1.4 ! misho     950:            sudoerserror(NULL);
1.1.1.2   misho     951:            debug_return_bool(false);
1.1       misho     952:        }
                    953:        istack[idepth].more = NULL;
                    954:     }
                    955:     /* Push the old (current) file and open the new one. */
                    956:     istack[idepth].path = sudoers; /* push old path */
                    957:     istack[idepth].bs = YY_CURRENT_BUFFER;
                    958:     istack[idepth].lineno = sudolineno;
                    959:     istack[idepth].keepopen = keepopen;
                    960:     idepth++;
                    961:     sudolineno = 1;
                    962:     sudoers = path;
1.1.1.4 ! misho     963:     sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
1.1       misho     964: 
1.1.1.2   misho     965:     debug_return_bool(true);
1.1       misho     966: }
                    967: 
1.1.1.2   misho     968: static bool
1.1       misho     969: pop_include(void)
                    970: {
                    971:     struct path_list *pl;
                    972:     FILE *fp;
1.1.1.2   misho     973:     debug_decl(pop_include, SUDO_DEBUG_PARSER)
1.1       misho     974: 
                    975:     if (idepth == 0)
1.1.1.2   misho     976:        debug_return_bool(false);
1.1       misho     977: 
                    978:     if (!keepopen)
                    979:        fclose(YY_CURRENT_BUFFER->yy_input_file);
1.1.1.4 ! misho     980:     sudoers_delete_buffer(YY_CURRENT_BUFFER);
1.1       misho     981:     /* If we are in an include dir, move to the next file. */
                    982:     while ((pl = istack[idepth - 1].more) != NULL) {
1.1.1.2   misho     983:        fp = open_sudoers(pl->path, false, &keepopen);
1.1       misho     984:        if (fp != NULL) {
                    985:            istack[idepth - 1].more = pl->next;
                    986:            efree(sudoers);
                    987:            sudoers = pl->path;
                    988:            sudolineno = 1;
1.1.1.4 ! misho     989:            sudoers_switch_to_buffer(sudoers_create_buffer(fp, YY_BUF_SIZE));
1.1       misho     990:            efree(pl);
                    991:            break;
                    992:        }
                    993:        /* Unable to open path in include dir, go to next one. */
                    994:        istack[idepth - 1].more = pl->next;
                    995:        efree(pl->path);
                    996:        efree(pl);
                    997:     }
                    998:     /* If no path list, just pop the last dir on the stack. */
                    999:     if (pl == NULL) {
                   1000:        idepth--;
1.1.1.4 ! misho    1001:        sudoers_switch_to_buffer(istack[idepth].bs);
1.1       misho    1002:        efree(sudoers);
                   1003:        sudoers = istack[idepth].path;
                   1004:        sudolineno = istack[idepth].lineno;
                   1005:        keepopen = istack[idepth].keepopen;
                   1006:     }
1.1.1.2   misho    1007:     debug_return_bool(true);
1.1       misho    1008: }
                   1009: 
                   1010: static char *
                   1011: parse_include(char *base)
                   1012: {
1.1.1.2   misho    1013:     char *cp, *ep, *path, *pp;
                   1014:     int dirlen = 0, len = 0, subst = 0;
1.1       misho    1015:     size_t shost_len = 0;
1.1.1.2   misho    1016:     debug_decl(parse_include, SUDO_DEBUG_PARSER)
1.1       misho    1017: 
                   1018:     /* Pull out path from #include line. */
                   1019:     cp = base + sizeof("#include");
                   1020:     if (*cp == 'i')
                   1021:        cp += 3; /* includedir */
                   1022:     while (isblank((unsigned char) *cp))
                   1023:        cp++;
                   1024:     ep = cp;
                   1025:     while (*ep != '\0' && !isspace((unsigned char) *ep)) {
                   1026:        if (ep[0] == '%' && ep[1] == 'h') {
                   1027:            shost_len = strlen(user_shost);
                   1028:            len += shost_len - 2;
                   1029:            subst = 1;
                   1030:        }
                   1031:        ep++;
                   1032:     }
                   1033: 
1.1.1.2   misho    1034:     /* Relative paths are located in the same dir as the sudoers file. */
                   1035:     if (*cp != '/') {
                   1036:        char *dirend = strrchr(sudoers, '/');
                   1037:        if (dirend != NULL)
                   1038:            dirlen = (int)(dirend - sudoers) + 1;
                   1039:     }
                   1040: 
                   1041:     /* Make a copy of the fully-qualified path and return it. */
1.1       misho    1042:     len += (int)(ep - cp);
1.1.1.2   misho    1043:     path = pp = malloc(len + dirlen + 1);
                   1044:     if (path == NULL) {
1.1.1.4 ! misho    1045:        warning(NULL);
        !          1046:        sudoerserror(NULL);
1.1.1.2   misho    1047:        debug_return_str(NULL);
                   1048:     }
                   1049:     if (dirlen) {
                   1050:        memcpy(path, sudoers, dirlen);
                   1051:        pp += dirlen;
1.1       misho    1052:     }
                   1053:     if (subst) {
                   1054:        /* substitute for %h */
                   1055:        while (cp < ep) {
                   1056:            if (cp[0] == '%' && cp[1] == 'h') {
                   1057:                memcpy(pp, user_shost, shost_len);
                   1058:                pp += shost_len;
                   1059:                cp += 2;
                   1060:                continue;
                   1061:            }
                   1062:            *pp++ = *cp++;
                   1063:        }
                   1064:        *pp = '\0';
                   1065:     } else {
1.1.1.2   misho    1066:        memcpy(pp, cp, len);
                   1067:        pp[len] = '\0';
1.1       misho    1068:     }
                   1069: 
                   1070:     /* Push any excess characters (e.g. comment, newline) back to the lexer */
                   1071:     if (*ep != '\0')
                   1072:        yyless((int)(ep - base));
                   1073: 
1.1.1.2   misho    1074:     debug_return_str(path);
1.1       misho    1075: }
                   1076: 
                   1077: #ifdef TRACELEXER
1.1.1.3   misho    1078: int
1.1       misho    1079: sudoers_trace_print(const char *msg)
                   1080: {
                   1081:     return fputs(msg, stderr);
                   1082: }
1.1.1.2   misho    1083: #else
1.1.1.3   misho    1084: int
1.1.1.2   misho    1085: sudoers_trace_print(const char *msg)
                   1086: {
                   1087:     static bool initialized;
                   1088:     static struct lbuf lbuf;
                   1089: 
                   1090:     if (!initialized) {
                   1091:        initialized = true;
                   1092:        lbuf_init(&lbuf, NULL, 0, NULL, 0);
                   1093:     }
                   1094: 
                   1095:     lbuf_append(&lbuf, "%s", msg);
                   1096:     /* XXX - assumes a final newline */
                   1097:     if (strchr(msg, '\n') != NULL)
                   1098:     {
                   1099:        sudo_debug_printf2(NULL, NULL, 0, SUDO_DEBUG_PARSER|SUDO_DEBUG_DEBUG,
                   1100:            "%s:%d %s", sudoers, sudolineno, lbuf.buf);
                   1101:        lbuf.len = 0;
                   1102:     }
                   1103:     return 0;
                   1104: }
1.1       misho    1105: #endif /* TRACELEXER */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>