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 all commits
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
1 change: 1 addition & 0 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ install: ${PROG} ${MAN}
chmod ${BINMODE} ${DESTDIR}${BINDIR}/${PROG}
cp -f doas.1 ${DESTDIR}${MANDIR}/man1
cp -f doas.conf.5 ${DESTDIR}${MANDIR}/man5
cp -f doas.d.5 ${DESTDIR}${MANDIR}/man5
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: could the installation of this file be optional?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure how to integrate it with the build system. Open to suggestions.


uninstall:
rm -f ${DESTDIR}${BINDIR}/${PROG}
Expand Down
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
85 changes: 85 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,82 @@ 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) {
if (errno != ENOENT)
err(1, "lstat(\"%s\")", dirpath);

errno = ENOTDIR;
return 0;
}

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;
int i, m, 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
if (dirent_count < 0)
err(1, checkperms ? "doas is not enabled, %s" :
"could not open config directory %s", dirpath);

for (i = 0, m = 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 (pathlen < 6)
continue;

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);
m++;
}

free(dirent_table);

if (!m)
errx(1, "doas is not enabled, %s: no matching configuration files found\n", dirpath);
}
#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,6 +263,11 @@ 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
#endif
kaniini marked this conversation as resolved.
Show resolved Hide resolved
parseconfig(confpath, 0);
if (!argc)
exit(0);
Expand Down Expand Up @@ -330,6 +410,11 @@ main(int argc, char **argv)
if (geteuid())
errx(1, "not installed setuid");

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

/* cmdline is used only for logging, no need to abort on truncate */
Expand Down
1 change: 1 addition & 0 deletions doas.conf.5
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,7 @@ permit nopass keepenv setenv { PATH } root as root
.Ed
.Sh SEE ALSO
.Xr doas 1 ,
.Xr doas.d 5 ,
.Xr syslogd 8
.Sh HISTORY
The
Expand Down
50 changes: 50 additions & 0 deletions doas.d.5
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
.\"Copyright (c) 2021 Ariadne Conill <[email protected]>
.\"
.\"Permission to use, copy, modify, and distribute this software for any
.\"purpose with or without fee is hereby granted, provided that the above
.\"copyright notice and this permission notice appear in all copies.
.\"
.\"THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
.\"WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
.\"MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
.\"ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
.\"WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
.\"ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
.\"OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
.Dd $Mdocdate: October 9 2020 $
.Dt DOAS.CONF 5
.Os
.Sh NAME
.Nm doas.conf
.Nd doas configuration file
.Sh DESCRIPTION
The
.Xr doas 1
utility executes commands as other users according to the rules
configured in either the configuration file or, optionally, the
configuration directory. The preference to use the configuration
file or configuration directory is determined at compile time,
.Xr doas 1
will only consult one or the other.
.Pp
Configuration snippets stored in the configuration directory
follow the same rules as the classic
.Xr doas 1
configuration file, documented in
.Xr doas.conf 5 .
They must end with the .conf extension, or they will be ignored.
.Pp
These snippets are read in alphabetical order and thus can be
ordered in the same way as other configuration directories.
.Sh FILES
.Bl -tag -width /etc/doas.d -compact
.It Pa /etc/doas.d
.Xr doas 1
configuration directory.
.Sh SEE ALSO
.Xr doas 1 ,
.Xr doas.conf 5
.Sh HISTORY
The
.Nm
configuration directory first appeared in OpenDoas.
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