diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2007-10-13 16:35:23 +0000 |
commit | 3bc6f4c74e1cc60c05a1ab152805af447144952a (patch) | |
tree | 4a68ea922315ee6f6d1396cafc87ae97f4d0d06f /sbin/ipsecctl/parse.y | |
parent | 3270c1ab5c203bfd16890aaf55afd4c31904e523 (diff) |
in all these programs using the same pfctl-derived parse.y, re-unify the
yylex implementation and the code which interacts with yylex. this also
brings the future potential for include support to all of the parsers.
in the future please do not silly modifications to one of these files
without checking if you are de-unifying the code.
checked by developers in all these areas.
Diffstat (limited to 'sbin/ipsecctl/parse.y')
-rw-r--r-- | sbin/ipsecctl/parse.y | 209 |
1 files changed, 149 insertions, 60 deletions
diff --git a/sbin/ipsecctl/parse.y b/sbin/ipsecctl/parse.y index ccfe17cb2b2..0bfd11e8612 100644 --- a/sbin/ipsecctl/parse.y +++ b/sbin/ipsecctl/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.127 2007/10/11 14:39:16 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.128 2007/10/13 16:35:18 deraadt Exp $ */ /* * Copyright (c) 2002, 2003, 2004 Henning Brauer <henning@openbsd.org> @@ -47,12 +47,41 @@ #include "ipsecctl.h" +TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); +static struct file { + TAILQ_ENTRY(file) entry; + FILE *stream; + char *name; + int lineno; + int errors; +} *file; +struct file *pushfile(const char *, int); +int popfile(void); +int check_file_secrecy(int, const char *); +int yyparse(void); +int yylex(void); +int yyerror(const char *, ...); +int kw_cmp(const void *, const void *); +int lookup(char *); +int lgetc(int); +int lungetc(int); +int findeol(void); + +TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); +struct sym { + TAILQ_ENTRY(sym) entry; + int used; + int persist; + char *nam; + char *val; +}; +int symset(const char *, const char *, int); +char *symget(const char *); +int cmdline_symset(char *); + #define KEYSIZE_LIMIT 1024 static struct ipsecctl *ipsec = NULL; -static FILE *fin = NULL; -static int lineno = 1; -static int errors = 0; static int debug = 0; const struct ipsec_xf authxfs[] = { @@ -110,27 +139,6 @@ const struct ipsec_xf groupxfs[] = { { NULL, 0, 0, 0 }, }; -int yyerror(const char *, ...); -int yyparse(void); -int kw_cmp(const void *, const void *); -int lookup(char *); -int lgetc(int); -int lungetc(int); -int findeol(void); -int yylex(void); - -TAILQ_HEAD(symhead, sym) symhead = TAILQ_HEAD_INITIALIZER(symhead); -struct sym { - TAILQ_ENTRY(sym) entries; - int used; - int persist; - char *nam; - char *val; -}; - -int symset(const char *, const char *, int); -int cmdline_symset(char *); -char *symget(const char *); int atoul(char *, u_long *); int atospi(char *, u_int32_t *); u_int8_t x2i(unsigned char *); @@ -271,7 +279,7 @@ grammar : /* empty */ | grammar sarule '\n' | grammar tcpmd5rule '\n' | grammar varset '\n' - | grammar error '\n' { errors++; } + | grammar error '\n' { file->errors++; } ; comma : ',' @@ -823,11 +831,10 @@ int yyerror(const char *fmt, ...) { va_list ap; - extern const char *infile; - errors = 1; + file->errors++; va_start(ap, fmt); - fprintf(stderr, "%s: %d: ", infile, yylval.lineno); + fprintf(stderr, "%s: %d: ", file->name, yylval.lineno); vfprintf(stderr, fmt, ap); fprintf(stderr, "\n"); va_end(ap); @@ -915,10 +922,9 @@ char pushback_buffer[MAXPUSHBACK]; int pushback_index = 0; int -lgetc(int inquot) +lgetc(int quotec) { - int c, next; - FILE *f = fin; + int c, next; if (parsebuf) { /* Read character from the parsebuffer instead of input. */ @@ -934,29 +940,39 @@ lgetc(int inquot) if (pushback_index) return (pushback_buffer[--pushback_index]); - if (inquot) { - c = getc(f); + if (quotec) { + if ((c = getc(file->stream)) == EOF) { + yyerror("reached end of file while parsing quoted string"); + if (popfile() == EOF) + return (EOF); + return (quotec); + } return (c); } - while ((c = getc(f)) == '\\') { - next = getc(f); + while ((c = getc(file->stream)) == '\\') { + next = getc(file->stream); if (next != '\n') { c = next; break; } - yylval.lineno = lineno; - lineno++; + yylval.lineno = file->lineno; + file->lineno++; } if (c == '\t' || c == ' ') { /* Compress blanks to a single space. */ do { - c = getc(f); + c = getc(file->stream); } while (c == '\t' || c == ' '); - ungetc(c, f); + ungetc(c, file->stream); c = ' '; } + while (c == EOF) { + if (popfile() == EOF) + return (EOF); + c = getc(file->stream); + } return (c); } @@ -988,7 +1004,7 @@ findeol(void) while (1) { c = lgetc(0); if (c == '\n') { - lineno++; + file->lineno++; break; } if (c == EOF) @@ -1002,7 +1018,7 @@ yylex(void) { char buf[8096]; char *p, *val; - int endc, next, c; + int quotec, next, c; int token; top: @@ -1010,7 +1026,7 @@ top: while ((c = lgetc(0)) == ' ') ; /* nothing */ - yylval.lineno = lineno; + yylval.lineno = file->lineno; if (c == '#') while ((c = lgetc(0)) != '\n' && c != EOF) ; /* nothing */ @@ -1044,21 +1060,21 @@ top: switch (c) { case '\'': case '"': - endc = c; + quotec = c; while (1) { - if ((c = lgetc(1)) == EOF) + if ((c = lgetc(quotec)) == EOF) return (0); if (c == '\n') { - lineno++; + file->lineno++; continue; } else if (c == '\\') { - if ((next = lgetc(1)) == EOF) + if ((next = lgetc(quotec)) == EOF) return (0); - if (next == endc) + if (next == quotec) c = next; else lungetc(next); - } else if (c == endc) { + } else if (c == quotec) { *p = '\0'; break; } @@ -1132,8 +1148,8 @@ nodigits: return (token); } if (c == '\n') { - yylval.lineno = lineno; - lineno++; + yylval.lineno = file->lineno; + file->lineno++; } if (c == EOF) return (0); @@ -1141,25 +1157,98 @@ nodigits: } int -parse_rules(FILE *input, struct ipsecctl *ipsecx) +check_file_secrecy(int fd, const char *fname) +{ + struct stat st; + + if (fstat(fd, &st)) { + warn("cannot stat %s", fname); + return (-1); + } + if (st.st_uid != 0 && st.st_uid != getuid()) { + warnx("%s: owner not root or current user", fname); + return (-1); + } + if (st.st_mode & (S_IRWXG | S_IRWXO)) { + warnx("%s: group/world readable/writeable", fname); + return (-1); + } + return (0); +} + +struct file * +pushfile(const char *name, int secret) +{ + struct file *nfile; + + if ((nfile = calloc(1, sizeof(struct file))) == NULL || + (nfile->name = strdup(name)) == NULL) + return (NULL); + if (TAILQ_FIRST(&files) == NULL && strcmp(nfile->name, "-") == 0) { + nfile->stream = stdin; + free(nfile->name); + if ((nfile->name = strdup("stdin")) == NULL) { + free(nfile); + return (NULL); + } + } else if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { + free(nfile->name); + free(nfile); + return (NULL); + } else if (secret && + check_file_secrecy(fileno(nfile->stream), nfile->name)) { + fclose(nfile->stream); + free(nfile->name); + free(nfile); + return (NULL); + } + nfile->lineno = 1; + TAILQ_INSERT_TAIL(&files, nfile, entry); + return (nfile); +} + +int +popfile(void) +{ + struct file *prev; + + if ((prev = TAILQ_PREV(file, files, entry)) != NULL) { + prev->errors += file->errors; + TAILQ_REMOVE(&files, file, entry); + fclose(file->stream); + free(file->name); + free(file); + file = prev; + return (0); + } + return (EOF); +} + +int +parse_rules(const char *filename, struct ipsecctl *ipsecx) { struct sym *sym; + int errors = 0; ipsec = ipsecx; - fin = input; - lineno = 1; - errors = 0; + + if ((file = pushfile(filename, 1)) == NULL) { + warn("cannot open the main config file!"); + return (-1); + } yyparse(); + errors = file->errors; + popfile(); /* Free macros and check which have not been used. */ while ((sym = TAILQ_FIRST(&symhead))) { if ((ipsec->opts & IPSECCTL_OPT_VERBOSE2) && !sym->used) fprintf(stderr, "warning: macro '%s' not " "used\n", sym->nam); - TAILQ_REMOVE(&symhead, sym, entries); free(sym->nam); free(sym->val); + TAILQ_REMOVE(&symhead, sym, entry); free(sym); } @@ -1172,16 +1261,16 @@ symset(const char *nam, const char *val, int persist) struct sym *sym; for (sym = TAILQ_FIRST(&symhead); sym && strcmp(nam, sym->nam); - sym = TAILQ_NEXT(sym, entries)) + sym = TAILQ_NEXT(sym, entry)) ; /* nothing */ if (sym != NULL) { if (sym->persist == 1) return (0); else { - TAILQ_REMOVE(&symhead, sym, entries); free(sym->nam); free(sym->val); + TAILQ_REMOVE(&symhead, sym, entry); free(sym); } } @@ -1201,7 +1290,7 @@ symset(const char *nam, const char *val, int persist) } sym->used = 0; sym->persist = persist; - TAILQ_INSERT_TAIL(&symhead, sym, entries); + TAILQ_INSERT_TAIL(&symhead, sym, entry); return (0); } @@ -1232,7 +1321,7 @@ symget(const char *nam) { struct sym *sym; - TAILQ_FOREACH(sym, &symhead, entries) + TAILQ_FOREACH(sym, &symhead, entry) if (strcmp(nam, sym->nam) == 0) { sym->used = 1; return (sym->val); |