Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add --with-doas-confdir feature #71

Open
wants to merge 8 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,12 @@ similar to sudo.

See the comment block in `timestamp.c` for an in-depth description on how
timestamps are created and checked to be as safe as possible.

### `--with-doas-confdir`

An optional feature can be enabled which will result in `doas` reading configuration
snippets from `/etc/doas.d`. These configuration snippets have the same requirements
as `/etc/doas.conf` (owned by root, not world-writable).

If this feature is enabled, only the `/etc/doas.d` directory is read, and the historical
`/etc/doas.conf` file is ignored.
8 changes: 8 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ usage: configure [options]
--without-shadow disable shadow support

--with-timestamp enable timestamp support
--with-doas-confdir enable configuration directory support

--uid-max=NUM set UID_MAX (default 65535)
--gid-max=NUM set GID_MAX (default 65535)
Expand All @@ -38,6 +39,7 @@ EOF

# defaults
WITHOUT_TIMESTAMP=yes
WITHOUT_CONFDIR=yes
UID_MAX=65535
GID_MAX=65535

Expand All @@ -56,6 +58,8 @@ for x; do
--target) TARGET=$var ;;
--enable-debug) DEBUG=yes ;;
--enable-static) BUILD_STATIC=yes ;;
--with-doas-confdir) WITHOUT_CONFDIR= ;;
--without-doas-confdir) WITHOUT_CONFDIR=yes ;;
--with-pam) WITHOUT_PAM=; WITHOUT_SHADOW=yes ;;
--with-shadow) WITHOUT_SHADOW=; WITHOUT_PAM=yes ;;
--without-pam) WITHOUT_PAM=yes ;;
Expand Down Expand Up @@ -558,4 +562,8 @@ fi

printf '#define DOAS_CONF "%s/doas.conf"\n' "${SYSCONFDIR}" >>$CONFIG_H

if [ -z "$WITHOUT_CONFDIR" ]; then
printf '#define DOAS_CONFDIR "%s/doas.d"\n' "${SYSCONFDIR}" >>$CONFIG_H
fi

printf '\n#endif /* CONFIG_H */\n' >>$CONFIG_H
72 changes: 72 additions & 0 deletions doas.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <syslog.h>
#include <errno.h>
#include <fcntl.h>
#include <dirent.h>

#include "openbsd.h"
#include "doas.h"
Expand Down Expand Up @@ -155,6 +156,7 @@ permit(uid_t uid, gid_t *groups, int ngroups, const struct rule **lastr,
static void
parseconfig(const char *filename, int checkperms)
{
extern const char *yyfn;
extern FILE *yyfp;
extern int yyparse(void);
struct stat sb;
Expand All @@ -164,6 +166,8 @@ parseconfig(const char *filename, int checkperms)
err(1, checkperms ? "doas is not enabled, %s" :
"could not open config file %s", filename);

yyfn = filename;

if (checkperms) {
if (fstat(fileno(yyfp), &sb) != 0)
err(1, "fstat(\"%s\")", filename);
Expand All @@ -174,11 +178,67 @@ parseconfig(const char *filename, int checkperms)
}

yyparse();
yyfn = NULL;

fclose(yyfp);
if (parse_errors)
exit(1);
}

#ifdef DOAS_CONFDIR
static int
isconfdir(const char *dirpath)
{
struct stat sb;

if (lstat(dirpath, &sb) != 0)
err(1, "lstat(\"%s\")", dirpath);
Duncaen marked this conversation as resolved.
Show resolved Hide resolved

if ((sb.st_mode & (S_IFMT)) == S_IFDIR)
return 1;

errno = ENOTDIR;
return 0;
}

static void
parseconfdir(const char *dirpath, int checkperms)
{
struct dirent **dirent_table;
size_t i, dirent_count;
char pathbuf[PATH_MAX];

if (!isconfdir(dirpath))
err(1, checkperms ? "doas is not enabled, %s" :
"could not open config directory %s", dirpath);

dirent_count = scandir(dirpath, &dirent_table, NULL, alphasort);
Duncaen marked this conversation as resolved.
Show resolved Hide resolved

for (i = 0; i < dirent_count; i++)
{
Duncaen marked this conversation as resolved.
Show resolved Hide resolved
struct stat sb;
size_t pathlen;

pathlen = snprintf(pathbuf, sizeof pathbuf, "%s/%s", dirpath, dirent_table[i]->d_name);
free(dirent_table[i]);

/* make sure path ends in .conf */
if (strcmp(pathbuf + (pathlen - 5), ".conf"))
Duncaen marked this conversation as resolved.
Show resolved Hide resolved
continue;

if (stat(pathbuf, &sb) != 0)
err(1, "stat(\"%s\")", pathbuf);

if ((sb.st_mode & (S_IFMT)) != S_IFREG)
continue;

parseconfig(pathbuf, checkperms);
}

free(dirent_table);
}
#endif

static void __dead
checkconfig(const char *confpath, int argc, char **argv,
uid_t uid, gid_t *groups, int ngroups, uid_t target)
Expand All @@ -188,7 +248,13 @@ checkconfig(const char *confpath, int argc, char **argv,
if (setresuid(uid, uid, uid) != 0)
err(1, "setresuid");

#ifdef DOAS_CONFDIR
if (isconfdir(confpath))
parseconfdir(confpath, 0);
else
#else
parseconfig(confpath, 0);
#endif
kaniini marked this conversation as resolved.
Show resolved Hide resolved
if (!argc)
exit(0);

Expand Down Expand Up @@ -330,7 +396,13 @@ main(int argc, char **argv)
if (geteuid())
errx(1, "not installed setuid");

#ifdef DOAS_CONFDIR
if (isconfdir(DOAS_CONFDIR))
parseconfdir(DOAS_CONFDIR, 1);
else
#else
parseconfig(DOAS_CONF, 1);
#endif

/* cmdline is used only for logging, no need to abort on truncate */
(void)strlcpy(cmdline, argv[0], sizeof(cmdline));
Expand Down
3 changes: 2 additions & 1 deletion parse.y
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ typedef struct {
} yystype;
#define YYSTYPE yystype

const char *yyfn;
kaniini marked this conversation as resolved.
Show resolved Hide resolved
FILE *yyfp;

struct rule **rules;
Expand Down Expand Up @@ -203,7 +204,7 @@ yyerror(const char *fmt, ...)
va_start(va, fmt);
vfprintf(stderr, fmt, va);
va_end(va);
fprintf(stderr, " at line %d\n", yylval.lineno + 1);
fprintf(stderr, " at %s, line %d\n", yyfn, yylval.lineno + 1);
parse_errors++;
}

Expand Down