summaryrefslogtreecommitdiff
path: root/usr.sbin/hostapd/parse.y
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/hostapd/parse.y')
-rw-r--r--usr.sbin/hostapd/parse.y190
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,