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 /usr.sbin/hostapd | |
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 'usr.sbin/hostapd')
-rw-r--r-- | usr.sbin/hostapd/parse.y | 190 |
1 files changed, 105 insertions, 85 deletions
diff --git a/usr.sbin/hostapd/parse.y b/usr.sbin/hostapd/parse.y index fdbc297616e..793c25bd3a0 100644 --- a/usr.sbin/hostapd/parse.y +++ b/usr.sbin/hostapd/parse.y @@ -1,4 +1,4 @@ -/* $OpenBSD: parse.y,v 1.31 2007/10/11 14:39:17 deraadt Exp $ */ +/* $OpenBSD: parse.y,v 1.32 2007/10/13 16:35:20 deraadt Exp $ */ /* * Copyright (c) 2004, 2005, 2006 Reyk Floeter <reyk@openbsd.org> @@ -53,21 +53,29 @@ #include <string.h> #include <unistd.h> #include <stdint.h> +#include <err.h> #include "hostapd.h" -extern struct hostapd_config hostapd_cfg; -static int errors = 0; - -TAILQ_HEAD(filehead, file) filehead = TAILQ_HEAD_INITIALIZER(filehead); -struct file { +TAILQ_HEAD(files, file) files = TAILQ_HEAD_INITIALIZER(files); +static struct file { TAILQ_ENTRY(file) entry; - - char *name; FILE *stream; + char *name; int lineno; -}; -static struct file *file; + 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 { @@ -77,18 +85,10 @@ struct sym { char *nam; char *val; }; - -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); int symset(const char *, const char *, int); char *symget(const char *); -struct file *hostapd_add_file(struct hostapd_config *, const char *); + +extern struct hostapd_config hostapd_cfg; typedef struct { union { @@ -181,7 +181,7 @@ grammar : /* empty */ | grammar option '\n' | grammar event '\n' | grammar varset '\n' - | grammar error '\n' { errors++; } + | grammar error '\n' { file->errors++; } ; include : INCLUDE STRING @@ -189,7 +189,7 @@ include : INCLUDE STRING struct file *nfile; if ((nfile = - hostapd_add_file(&hostapd_cfg, $2)) == NULL) { + pushfile($2, 1)) == NULL) { yyerror("failed to include file %s", $2); free($2); YYERROR; @@ -1331,10 +1331,9 @@ char pushback_buffer[MAXPUSHBACK]; int pushback_index = 0; int -lgetc(int inquot) +lgetc(int quotec) { - int c, next; - struct file *pfile; + int c, next; if (parsebuf) { /* Read character from the parsebuffer instead of input. */ @@ -1350,8 +1349,13 @@ lgetc(int inquot) if (pushback_index) return (pushback_buffer[--pushback_index]); - if (inquot) { - c = getc(file->stream); + 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); } @@ -1369,22 +1373,15 @@ lgetc(int inquot) do { c = getc(file->stream); } while (c == '\t' || c == ' '); - if (ungetc(c, file->stream) == EOF) - hostapd_fatal("lgetc: ungetc"); + ungetc(c, file->stream); c = ' '; } - while (c == EOF && - (pfile = TAILQ_PREV(file, filehead, entry)) != NULL) { - fclose(file->stream); - free(file->name); - TAILQ_REMOVE(&filehead, file, entry); - free(file); - - file = pfile; + while (c == EOF) { + if (popfile() == EOF) + return (EOF); c = getc(file->stream); } - return (c); } @@ -1430,7 +1427,7 @@ yylex(void) { char buf[8096]; char *p, *val; - int endc, c; + int quotec, next, c; int token; top: @@ -1472,17 +1469,23 @@ 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 == endc) { - *p = '\0'; - break; - } if (c == '\n') { file->lineno++; continue; + } else if (c == '\\') { + if ((next = lgetc(quotec)) == EOF) + return (0); + if (next == quotec) + c = next; + else + lungetc(next); + } else if (c == quotec) { + *p = '\0'; + break; } if (p + 1 >= buf + sizeof(buf) - 1) { yyerror("string too long"); @@ -1640,50 +1643,75 @@ symget(const char *nam) return (NULL); } -struct file * -hostapd_add_file(struct hostapd_config *cfg, const char *name) +int +check_file_secrecy(int fd, const char *fname) { - struct file *nfile = NULL; + struct stat st; - if ((nfile = calloc(1, sizeof(struct file))) == NULL) - return (NULL); - - if ((nfile->name = strdup(name)) == NULL) - goto err; - - if ((nfile->stream = fopen(name, "rb")) == NULL) { - hostapd_log(HOSTAPD_LOG, "failed to open %s", name); - goto err; + if (fstat(fd, &st)) { + warn("cannot stat %s", fname); + return (-1); } - - if (hostapd_check_file_secrecy(fileno(nfile->stream), name)) { - hostapd_log(HOSTAPD_LOG, "invalid permissions for %s", name); - goto err; + 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); +} - nfile->lineno = 1; - TAILQ_INSERT_TAIL(&filehead, nfile, entry); - - return (nfile); +struct file * +pushfile(const char *name, int secret) +{ + struct file *nfile; - err: - if (nfile->name != NULL) + if ((nfile = calloc(1, sizeof(struct file))) == NULL || + (nfile->name = strdup(name)) == NULL) + return (NULL); + if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { free(nfile->name); - if (nfile->stream != NULL) + free(nfile); + return (NULL); + } else if (secret && + check_file_secrecy(fileno(nfile->stream), nfile->name)) { fclose(nfile->stream); - free(nfile); + free(nfile->name); + free(nfile); + return (NULL); + } + nfile->lineno = 1; + TAILQ_INSERT_TAIL(&files, nfile, entry); + return (nfile); +} - return (NULL); +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 hostapd_parse_file(struct hostapd_config *cfg) { struct sym *sym, *next; - struct file *nfile; + int errors = 0; int ret; - if ((file = hostapd_add_file(cfg, cfg->c_config)) == NULL) + if ((file = pushfile(cfg->c_config, 1)) == NULL) hostapd_fatal("failed to open the main config file: %s\n", cfg->c_config); @@ -1697,17 +1725,9 @@ hostapd_parse_file(struct hostapd_config *cfg) cfg->c_apme_hopdelay.tv_sec = HOSTAPD_HOPPER_MDELAY / 1000; cfg->c_apme_hopdelay.tv_usec = (HOSTAPD_HOPPER_MDELAY % 1000) * 1000; - errors = 0; - ret = yyparse(); - - for (file = TAILQ_FIRST(&filehead); file != NULL; file = nfile) { - nfile = TAILQ_NEXT(file, entry); - fclose(file->stream); - free(file->name); - TAILQ_REMOVE(&filehead, file, entry); - free(file); - } + errors = file->errors; + popfile(); /* Free macros and check which have not been used. */ for (sym = TAILQ_FIRST(&symhead); sym != NULL; sym = next) { @@ -1729,10 +1749,10 @@ hostapd_parse_file(struct hostapd_config *cfg) int yyerror(const char *fmt, ...) { - va_list ap; - char *nfmt; + va_list ap; + char *nfmt; - errors = 1; + file->errors++; va_start(ap, fmt); if (asprintf(&nfmt, "%s:%d: %s\n", file->name, yylval.lineno, |