=================================================================== RCS file: /cvs/cvs/blind/parse.y,v retrieving revision 1.3 retrieving revision 1.4 diff -u -p -r1.3 -r1.4 --- blind/parse.y 2022/03/20 18:47:16 1.3 +++ blind/parse.y 2022/03/20 20:40:36 1.4 @@ -16,9 +16,11 @@ %{ #include +#include #include #include +#include #include "blind.h" #include "log.h" @@ -36,18 +38,20 @@ static struct file { int errors; } *file, *top; -int yylex(void); -int yyerror(const char *, ...); -int config_load(struct blind *); -struct file *config_push(const char *); +int yylex(void); +int yyerror(const char *, ...); +int config_load(struct blind *); +struct file *config_push(const char *); +int config_pop(void); +int config_perm(int, const char *); -struct blind *env = NULL; -static int errors = 0; +struct blind *env = NULL; +static int errors = 0; typedef struct { union { - int64_t number; - char *string; + int64_t number; + char *string; } v; int lineno; } YYSTYPE; @@ -95,8 +99,13 @@ config_load(struct blind *temp) } top = file; - // parse config + // parse file + errors = file->errors; + config_pop(); + + // setup + return (0); } @@ -106,26 +115,76 @@ config_push(const char *name) struct file *nfile; if ((nfile = calloc(1, sizeof(struct file))) == NULL) { - log_debug("%s", __func__); + log_debug("%s: calloc()", __func__); return (NULL); } - if ((nfile->name = strdup(name)) == NULL) { - log_debug("%s", __func__); + log_debug("%s: strdup()", __func__); free(nfile); return (NULL); } - if ((nfile->stream = fopen(nfile->name, "r")) == NULL) { - log_debug("%s: %s", __func__, nfile->name); + log_debug("%s: fopen()", __func__); free(nfile->name); free(nfile); return (NULL); } + if (config_perm(fileno(nfile->stream), nfile->name)) { + fclose(nfile->stream); + free(nfile->name); + free(nfile); + return (NULL); + } + nfile->lineno = TAILQ_EMPTY(&files) ? 1 : 0; + nfile->ungetsize = 16; + nfile->ungetbuf = malloc(nfile->ungetsize); + if (nfile->ungetbuf == NULL) { + log_debug("%s: malloc()", __func__); + fclose(nfile->stream); + free(nfile->name); + free(nfile); + return (NULL); + } + TAILQ_INSERT_TAIL(&files, nfile, entry); + return (nfile); +} - // check file permission +int +config_pop(void) +{ + struct file *prv; - // load file + if ((prv = TAILQ_PREV(file, files, entry)) != NULL) + prv->errors += file->errors; - return (nfile); + TAILQ_REMOVE(&files, file, entry); + fclose(file->stream); + free(file->name); + free(file->ungetbuf); + free(file); + file = prv; + + return (file ? 0 : EOF); +} + +int +config_perm(int fd, const char *name) +{ + struct stat st; + + if (fstat(fd, &st)) { + log_debug("%s: fstat(%s)", __func__, name); + return (-1); + } + if (st.st_uid != 0 && st.st_uid != getuid()) { + log_debug("%s: %s: wrong file permission", \ + __func__, name); + return (-1); + } + if (st.st_mode & (S_IWGRP | S_IXGRP | S_IRWXO)) { + log_debug("%s: %s: group/world readable/writable", \ + __func__, name); + return (-1); + } + return (0); }