New debug framework for sudo and plugins using /etc/sudo.conf that
also supports function call tracing.
This commit is contained in:
2
MANIFEST
2
MANIFEST
@@ -16,6 +16,7 @@ common/fmt_string.c
|
|||||||
common/lbuf.c
|
common/lbuf.c
|
||||||
common/list.c
|
common/list.c
|
||||||
common/setgroups.c
|
common/setgroups.c
|
||||||
|
common/sudo_debug.c
|
||||||
common/term.c
|
common/term.c
|
||||||
common/zero_bytes.c
|
common/zero_bytes.c
|
||||||
compat/Makefile.in
|
compat/Makefile.in
|
||||||
@@ -101,6 +102,7 @@ include/gettext.h
|
|||||||
include/lbuf.h
|
include/lbuf.h
|
||||||
include/list.h
|
include/list.h
|
||||||
include/missing.h
|
include/missing.h
|
||||||
|
include/sudo_debug.h
|
||||||
include/sudo_plugin.h
|
include/sudo_plugin.h
|
||||||
indent.pro
|
indent.pro
|
||||||
install-sh
|
install-sh
|
||||||
|
@@ -42,8 +42,8 @@ DEFS = @OSDEFS@
|
|||||||
|
|
||||||
SHELL = @SHELL@
|
SHELL = @SHELL@
|
||||||
|
|
||||||
LTOBJS = alloc.lo atobool.lo fileops.lo fmt_string.lo \
|
LTOBJS = alloc.lo atobool.lo fileops.lo fmt_string.lo lbuf.lo list.lo \
|
||||||
lbuf.lo list.lo setgroups.lo term.lo zero_bytes.lo @COMMON_OBJS@
|
setgroups.lo sudo_debug.lo term.lo zero_bytes.lo @COMMON_OBJS@
|
||||||
|
|
||||||
all: libcommon.la
|
all: libcommon.la
|
||||||
|
|
||||||
@@ -115,6 +115,10 @@ list.lo: $(srcdir)/list.c $(top_builddir)/config.h $(incdir)/missing.h \
|
|||||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/list.c
|
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/list.c
|
||||||
setgroups.lo: $(srcdir)/setgroups.c $(top_builddir)/config.h $(incdir)/missing.h
|
setgroups.lo: $(srcdir)/setgroups.c $(top_builddir)/config.h $(incdir)/missing.h
|
||||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/setgroups.c
|
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/setgroups.c
|
||||||
|
sudo_debug.lo: $(srcdir)/sudo_debug.c $(top_builddir)/config.h \
|
||||||
|
$(incdir)/missing.h $(incdir)/alloc.h $(incdir)/error.h \
|
||||||
|
$(incdir)/gettext.h $(incdir)/sudo_debug.h
|
||||||
|
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/sudo_debug.c
|
||||||
term.lo: $(srcdir)/term.c $(top_builddir)/config.h $(incdir)/missing.h
|
term.lo: $(srcdir)/term.c $(top_builddir)/config.h $(incdir)/missing.h
|
||||||
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/term.c
|
$(LIBTOOL) --mode=compile $(CC) -c -o $@ $(CPPFLAGS) $(CFLAGS) $(DEFS) $(srcdir)/term.c
|
||||||
zero_bytes.lo: $(srcdir)/zero_bytes.c $(top_builddir)/config.h \
|
zero_bytes.lo: $(srcdir)/zero_bytes.c $(top_builddir)/config.h \
|
||||||
|
381
common/sudo_debug.c
Normal file
381
common/sudo_debug.c
Normal file
@@ -0,0 +1,381 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/param.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#ifdef STDC_HEADERS
|
||||||
|
# include <stdlib.h>
|
||||||
|
# include <stddef.h>
|
||||||
|
#else
|
||||||
|
# ifdef HAVE_STDLIB_H
|
||||||
|
# include <stdlib.h>
|
||||||
|
# endif
|
||||||
|
#endif /* STDC_HEADERS */
|
||||||
|
#ifdef HAVE_STRING_H
|
||||||
|
# include <string.h>
|
||||||
|
#endif /* HAVE_STRING_H */
|
||||||
|
#ifdef HAVE_STRINGS_H
|
||||||
|
# include <strings.h>
|
||||||
|
#endif /* HAVE_STRINGS_H */
|
||||||
|
#ifdef HAVE_UNISTD_H
|
||||||
|
# include <unistd.h>
|
||||||
|
#endif /* HAVE_UNISTD_H */
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "missing.h"
|
||||||
|
#include "alloc.h"
|
||||||
|
#include "error.h"
|
||||||
|
#include "gettext.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The debug priorities and subsystems are currently hard-coded.
|
||||||
|
* In the future we might consider allowing plugins to register their
|
||||||
|
* own subsystems and provide direct access to the debugging API.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Note: this must match the order in sudo_debug.h */
|
||||||
|
const char *const sudo_debug_priorities[] = {
|
||||||
|
"crit",
|
||||||
|
"syserr",
|
||||||
|
"progerr",
|
||||||
|
"warn",
|
||||||
|
"notice",
|
||||||
|
"diag",
|
||||||
|
"info",
|
||||||
|
"trace",
|
||||||
|
"debug",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Note: this must match the order in sudo_debug.h */
|
||||||
|
const char *const sudo_debug_subsystems[] = {
|
||||||
|
"main",
|
||||||
|
"memory",
|
||||||
|
"args",
|
||||||
|
"exec",
|
||||||
|
"pty",
|
||||||
|
"utmp",
|
||||||
|
"conv",
|
||||||
|
"pcomm",
|
||||||
|
"util",
|
||||||
|
"list",
|
||||||
|
"netif",
|
||||||
|
"audit",
|
||||||
|
"edit",
|
||||||
|
"selinux",
|
||||||
|
"ldap",
|
||||||
|
"match",
|
||||||
|
"parser",
|
||||||
|
"alias",
|
||||||
|
"defaults",
|
||||||
|
"auth",
|
||||||
|
"env",
|
||||||
|
"logging",
|
||||||
|
"nss",
|
||||||
|
"rbtree",
|
||||||
|
"perms",
|
||||||
|
"plugin",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
#define NUM_SUBSYSTEMS (sizeof(sudo_debug_subsystems) / sizeof(sudo_debug_subsystems[0]) - 1)
|
||||||
|
|
||||||
|
static int sudo_debug_settings[NUM_SUBSYSTEMS];
|
||||||
|
static int sudo_debug_fd = -1;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Parse settings string from sudo.conf and open debugfile.
|
||||||
|
* Returns 1 on success, 0 if cannot open debugfile.
|
||||||
|
* Unsupported subsystems and priorities are silently ignored.
|
||||||
|
*/
|
||||||
|
int sudo_debug_init(const char *debugfile, const char *settings)
|
||||||
|
{
|
||||||
|
char *buf, *cp, *subsys, *pri;
|
||||||
|
int i, j;
|
||||||
|
|
||||||
|
/* Init per-subsystems settings to -1 since 0 is a valid priority. */
|
||||||
|
for (i = 0; i < NUM_SUBSYSTEMS; i++)
|
||||||
|
sudo_debug_settings[i] = -1;
|
||||||
|
|
||||||
|
/* Open debug file descriptor. */
|
||||||
|
if (sudo_debug_fd != -1)
|
||||||
|
close(sudo_debug_fd);
|
||||||
|
sudo_debug_fd = open(debugfile, O_WRONLY|O_APPEND|O_CREAT, S_IRUSR|S_IWUSR);
|
||||||
|
if (sudo_debug_fd == -1)
|
||||||
|
return 0;
|
||||||
|
(void)fcntl(sudo_debug_fd, F_SETFD, FD_CLOEXEC);
|
||||||
|
|
||||||
|
/* Parse settings string. */
|
||||||
|
buf = estrdup(settings);
|
||||||
|
for ((cp = strtok(buf, ",")); cp != NULL; (cp = strtok(NULL, ","))) {
|
||||||
|
/* Should be in the form subsys@pri. */
|
||||||
|
subsys = cp;
|
||||||
|
if ((pri = strchr(cp, '@')) == NULL)
|
||||||
|
continue;
|
||||||
|
*pri++ = '\0';
|
||||||
|
|
||||||
|
/* Look up priority and subsystem, fill in sudo_debug_settings[]. */
|
||||||
|
for (i = 0; sudo_debug_priorities[i] != NULL; i++) {
|
||||||
|
if (strcasecmp(pri, sudo_debug_priorities[i]) == 0) {
|
||||||
|
for (j = 0; sudo_debug_subsystems[j] != NULL; j++) {
|
||||||
|
if (strcasecmp(subsys, "all") == 0) {
|
||||||
|
sudo_debug_settings[j] = i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (strcasecmp(subsys, sudo_debug_subsystems[j]) == 0) {
|
||||||
|
sudo_debug_settings[j] = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
efree(buf);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sudo_debug_enter(const char *func, const char *file, int line,
|
||||||
|
int subsys)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "-> %s @ %s:%d", func,
|
||||||
|
file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit(const char *func, const char *file, int line,
|
||||||
|
int subsys)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d", func,
|
||||||
|
file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_int(const char *func, const char *file, int line,
|
||||||
|
int subsys, int rval)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %d", func,
|
||||||
|
file, line, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_long(const char *func, const char *file, int line,
|
||||||
|
int subsys, long rval)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %ld", func,
|
||||||
|
file, line, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_size_t(const char *func, const char *file, int line,
|
||||||
|
int subsys, size_t rval)
|
||||||
|
{
|
||||||
|
/* XXX - should use %zu but snprintf.c doesn't support it */
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %lu", func,
|
||||||
|
file, line, (unsigned long)rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_bool(const char *func, const char *file, int line,
|
||||||
|
int subsys, int rval)
|
||||||
|
{
|
||||||
|
if (rval == 0 || rval == 1) {
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %s",
|
||||||
|
func, file, line, rval ? "true" : "false");
|
||||||
|
} else {
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %d",
|
||||||
|
func, file, line, rval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_str(const char *func, const char *file, int line,
|
||||||
|
int subsys, const char *rval)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %s", func,
|
||||||
|
file, line, rval ? rval : "(null)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_str_masked(const char *func, const char *file, int line,
|
||||||
|
int subsys, const char *rval)
|
||||||
|
{
|
||||||
|
static const char stars[] = "********************************************************************************";
|
||||||
|
int len = rval ? strlen(rval) : sizeof("(null)") - 1;
|
||||||
|
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %.*s", func,
|
||||||
|
file, line, len, rval ? stars : "(null)");
|
||||||
|
}
|
||||||
|
|
||||||
|
void sudo_debug_exit_ptr(const char *func, const char *file, int line,
|
||||||
|
int subsys, const void *rval)
|
||||||
|
{
|
||||||
|
sudo_debug_printf2(subsys | SUDO_DEBUG_TRACE, "<- %s @ %s:%d := %p", func,
|
||||||
|
file, line, rval);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sudo_debug_write(const char *str, int len)
|
||||||
|
{
|
||||||
|
char *timestr;
|
||||||
|
time_t now;
|
||||||
|
ssize_t n;
|
||||||
|
struct iovec iov[5];
|
||||||
|
int iovcnt = 4;
|
||||||
|
|
||||||
|
if (sudo_debug_fd == -1 || len <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Prepend program name with trailing space. */
|
||||||
|
iov[1].iov_base = (char *)getprogname();
|
||||||
|
iov[1].iov_len = strlen(iov[1].iov_base);
|
||||||
|
iov[2].iov_base = " ";
|
||||||
|
iov[2].iov_len = 1;
|
||||||
|
|
||||||
|
/* Add string along with newline if it doesn't have one. */
|
||||||
|
iov[3].iov_base = (char *)str;
|
||||||
|
iov[3].iov_len = len;
|
||||||
|
if (str[len - 1] != '\n') {
|
||||||
|
/* force newline */
|
||||||
|
iov[4].iov_base = "\n";
|
||||||
|
iov[4].iov_len = 1;
|
||||||
|
iovcnt++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do timestamp last due to ctime's static buffer. */
|
||||||
|
now = time(NULL);
|
||||||
|
timestr = ctime(&now) + 4;
|
||||||
|
timestr[15] = ' '; /* replace year with a space */
|
||||||
|
timestr[16] = '\0';
|
||||||
|
iov[0].iov_base = timestr;
|
||||||
|
iov[0].iov_len = 16;
|
||||||
|
|
||||||
|
/* Write message in a single syscall */
|
||||||
|
n = writev(sudo_debug_fd, iov, iovcnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sudo_debug_printf2(int level, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
int buflen, pri, subsys;
|
||||||
|
va_list ap;
|
||||||
|
char *buf;
|
||||||
|
|
||||||
|
if (sudo_debug_fd == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Extract pri and subsystem from level. */
|
||||||
|
pri = SUDO_DEBUG_PRI(level);
|
||||||
|
subsys = SUDO_DEBUG_SUBSYS(level);
|
||||||
|
|
||||||
|
/* Make sure we want debug info at this level. */
|
||||||
|
if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri)
|
||||||
|
return;
|
||||||
|
|
||||||
|
va_start(ap, fmt);
|
||||||
|
buflen = vasprintf(&buf, fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
if (buflen != -1) {
|
||||||
|
sudo_debug_write(buf, buflen);
|
||||||
|
free(buf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[])
|
||||||
|
{
|
||||||
|
char * const *av;
|
||||||
|
char *buf, *cp;
|
||||||
|
int buflen, pri, subsys, log_envp = 0;
|
||||||
|
size_t plen;
|
||||||
|
|
||||||
|
if (sudo_debug_fd == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
#define EXEC_PREFIX "exec "
|
||||||
|
if (sudo_debug_fd == -1)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Extract pri and subsystem from level. */
|
||||||
|
pri = SUDO_DEBUG_PRI(level);
|
||||||
|
subsys = SUDO_DEBUG_SUBSYS(level);
|
||||||
|
|
||||||
|
/* Make sure we want debug info at this level. */
|
||||||
|
if (subsys >= NUM_SUBSYSTEMS || sudo_debug_settings[subsys] < pri)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Log envp for debug level "debug". */
|
||||||
|
if (sudo_debug_settings[subsys] >= SUDO_DEBUG_DEBUG - 1 && envp[0] != NULL)
|
||||||
|
log_envp = 1;
|
||||||
|
|
||||||
|
/* Alloc and build up buffer. */
|
||||||
|
plen = strlen(path);
|
||||||
|
buflen = sizeof(EXEC_PREFIX) -1 + plen;
|
||||||
|
if (argv[0] != NULL) {
|
||||||
|
buflen += sizeof(" []") - 1;
|
||||||
|
for (av = argv; *av; av++)
|
||||||
|
buflen += strlen(*av) + 1;
|
||||||
|
buflen--;
|
||||||
|
}
|
||||||
|
if (log_envp) {
|
||||||
|
buflen += sizeof(" []") - 1;
|
||||||
|
for (av = envp; *av; av++)
|
||||||
|
buflen += strlen(*av) + 1;
|
||||||
|
buflen--;
|
||||||
|
}
|
||||||
|
buf = malloc(buflen + 1);
|
||||||
|
if (buf == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* Copy prefix and command. */
|
||||||
|
memcpy(buf, EXEC_PREFIX, sizeof(EXEC_PREFIX) - 1);
|
||||||
|
cp = buf + sizeof(EXEC_PREFIX) - 1;
|
||||||
|
memcpy(cp, path, plen);
|
||||||
|
cp += plen;
|
||||||
|
|
||||||
|
/* Copy argv. */
|
||||||
|
if (argv[0] != NULL) {
|
||||||
|
*cp++ = ' ';
|
||||||
|
*cp++ = '[';
|
||||||
|
for (av = argv; *av; av++) {
|
||||||
|
size_t avlen = strlen(*av);
|
||||||
|
memcpy(cp, *av, avlen);
|
||||||
|
cp += avlen;
|
||||||
|
*cp++ = ' ';
|
||||||
|
}
|
||||||
|
cp[-1] = ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (log_envp) {
|
||||||
|
*cp++ = ' ';
|
||||||
|
*cp++ = '[';
|
||||||
|
for (av = envp; *av; av++) {
|
||||||
|
size_t avlen = strlen(*av);
|
||||||
|
memcpy(cp, *av, avlen);
|
||||||
|
cp += avlen;
|
||||||
|
*cp++ = ' ';
|
||||||
|
}
|
||||||
|
cp[-1] = ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
*cp = '\0';
|
||||||
|
|
||||||
|
sudo_debug_write(buf, buflen);
|
||||||
|
free(buf);
|
||||||
|
}
|
197
include/sudo_debug.h
Normal file
197
include/sudo_debug.h
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2011 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||||
|
*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _SUDO_DEBUG_H
|
||||||
|
#define _SUDO_DEBUG_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The priority and subsystem are encoded in a single 32-bit value.
|
||||||
|
* The lower 4 bits are the priority and the top 28 bits are the subsystem.
|
||||||
|
* This allows for 16 priorities and a very large number of subsystems.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sudo debug priorities, ordered least to most verbose,
|
||||||
|
* in other words, highest to lowest priority. Max pri is 15.
|
||||||
|
* Note: order must match sudo_debug_priorities[]
|
||||||
|
*/
|
||||||
|
#define SUDO_DEBUG_CRIT 1 /* critical errors */
|
||||||
|
#define SUDO_DEBUG_SYSERR 2 /* system errors */
|
||||||
|
#define SUDO_DEBUG_PROGERR 3 /* program errors */
|
||||||
|
#define SUDO_DEBUG_WARN 4 /* non-fatal warnings */
|
||||||
|
#define SUDO_DEBUG_NOTICE 5 /* non-error condition notices */
|
||||||
|
#define SUDO_DEBUG_DIAG 6 /* diagnostic messages */
|
||||||
|
#define SUDO_DEBUG_INFO 7 /* informational message */
|
||||||
|
#define SUDO_DEBUG_TRACE 8 /* log function enter/exit */
|
||||||
|
#define SUDO_DEBUG_DEBUG 9 /* very verbose debugging */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Sudo debug subsystems.
|
||||||
|
* This includes subsystems in the sudoers plugin.
|
||||||
|
* Note: order must match sudo_debug_subsystems[]
|
||||||
|
*/
|
||||||
|
#define SUDO_DEBUG_MAIN (1<<4) /* sudo main() */
|
||||||
|
#define SUDO_DEBUG_MEMORY (2<<4) /* memory subsystems */
|
||||||
|
#define SUDO_DEBUG_ARGS (3<<4) /* command line argument processing */
|
||||||
|
#define SUDO_DEBUG_EXEC (4<<4) /* command execution */
|
||||||
|
#define SUDO_DEBUG_PTY (5<<4) /* pseudo-tty */
|
||||||
|
#define SUDO_DEBUG_UTMP (6<<4) /* utmp file ops */
|
||||||
|
#define SUDO_DEBUG_CONV (7<<4) /* user conversation */
|
||||||
|
#define SUDO_DEBUG_PCOMM (8<<4) /* plugin communications */
|
||||||
|
#define SUDO_DEBUG_UTIL (9<<4) /* utility functions */
|
||||||
|
#define SUDO_DEBUG_LIST (10<<4) /* linked list functions */
|
||||||
|
#define SUDO_DEBUG_NETIF (11<<4) /* network interface functions */
|
||||||
|
#define SUDO_DEBUG_AUDIT (12<<4) /* audit */
|
||||||
|
#define SUDO_DEBUG_EDIT (13<<4) /* sudoedit */
|
||||||
|
#define SUDO_DEBUG_SELINUX (14<<4) /* selinux */
|
||||||
|
#define SUDO_DEBUG_LDAP (15<<4) /* sudoers LDAP */
|
||||||
|
#define SUDO_DEBUG_MATCH (16<<4) /* sudoers matching */
|
||||||
|
#define SUDO_DEBUG_PARSER (17<<4) /* sudoers parser */
|
||||||
|
#define SUDO_DEBUG_ALIAS (18<<4) /* sudoers alias functions */
|
||||||
|
#define SUDO_DEBUG_DEFAULTS (19<<4) /* sudoers defaults settings */
|
||||||
|
#define SUDO_DEBUG_AUTH (20<<4) /* authentication functions */
|
||||||
|
#define SUDO_DEBUG_ENV (21<<4) /* environment handling */
|
||||||
|
#define SUDO_DEBUG_LOGGING (22<<4) /* logging functions */
|
||||||
|
#define SUDO_DEBUG_NSS (23<<4) /* network service switch */
|
||||||
|
#define SUDO_DEBUG_RBTREE (24<<4) /* red-black tree functions */
|
||||||
|
#define SUDO_DEBUG_PERMS (25<<4) /* uid/gid swapping functions */
|
||||||
|
#define SUDO_DEBUG_PLUGIN (26<<4) /* main plugin functions */
|
||||||
|
#define SUDO_DEBUG_ALL 0xfff0 /* all subsystems */
|
||||||
|
|
||||||
|
/* Extract priority and convert to an index. */
|
||||||
|
#define SUDO_DEBUG_PRI(n) (((n) & 0xf) - 1)
|
||||||
|
|
||||||
|
/* Extract subsystem and convert to an index. */
|
||||||
|
#define SUDO_DEBUG_SUBSYS(n) (((n) >> 4) - 1)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrapper for sudo_debug_enter() that declares __func__ as needed
|
||||||
|
* and sets sudo_debug_subsys for sudo_debug_exit().
|
||||||
|
*/
|
||||||
|
#ifdef HAVE___FUNC__
|
||||||
|
# define debug_decl(funcname, subsys) \
|
||||||
|
const int sudo_debug_subsys = (subsys); \
|
||||||
|
sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
|
||||||
|
#else
|
||||||
|
# define debug_decl(funcname, subsys) \
|
||||||
|
const int sudo_debug_subsys = (subsys); \
|
||||||
|
const char *__func__ = #funcname; \
|
||||||
|
sudo_debug_enter(__func__, __FILE__, __LINE__, sudo_debug_subsys);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Wrappers for sudo_debug_exit() and friends.
|
||||||
|
*/
|
||||||
|
#define debug_return \
|
||||||
|
do { \
|
||||||
|
sudo_debug_exit(__func__, __FILE__, __LINE__, sudo_debug_subsys); \
|
||||||
|
return; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_int(rval) \
|
||||||
|
do { \
|
||||||
|
int sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_size_t(rval) \
|
||||||
|
do { \
|
||||||
|
size_t sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_size_t(__func__, __FILE__, __LINE__, sudo_debug_subsys,\
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_long(rval) \
|
||||||
|
do { \
|
||||||
|
long sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_long(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_bool(rval) \
|
||||||
|
do { \
|
||||||
|
int sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_bool(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_str(rval) \
|
||||||
|
do { \
|
||||||
|
const char *sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_str(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return (char *)sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_str_masked(rval) \
|
||||||
|
do { \
|
||||||
|
const char *sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_str_masked(__func__, __FILE__, __LINE__, \
|
||||||
|
sudo_debug_subsys, sudo_debug_rval); \
|
||||||
|
return (char *)sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define debug_return_ptr(rval) \
|
||||||
|
do { \
|
||||||
|
const void *sudo_debug_rval = (rval); \
|
||||||
|
sudo_debug_exit_ptr(__func__, __FILE__, __LINE__, sudo_debug_subsys, \
|
||||||
|
sudo_debug_rval); \
|
||||||
|
return (void *)sudo_debug_rval; \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Variadic macros are a C99 feature but GNU cpp has supported
|
||||||
|
* a (different) version of them for a long time.
|
||||||
|
*/
|
||||||
|
#if defined(__GNUC__) && __GNUC__ == 2
|
||||||
|
# define sudo_debug_printf(pri, fmt...) \
|
||||||
|
sudo_debug_printf2((pri)|sudo_debug_subsys, (fmt))
|
||||||
|
#else
|
||||||
|
# define sudo_debug_printf(pri, ...) \
|
||||||
|
sudo_debug_printf2((pri)|sudo_debug_subsys, __VA_ARGS__)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define sudo_debug_execve(pri, path, argv, envp) \
|
||||||
|
sudo_debug_execve2((pri)|sudo_debug_subsys, (path), (argv), (envp))
|
||||||
|
|
||||||
|
/*
|
||||||
|
* NULL-terminated string lists of priorities and subsystems.
|
||||||
|
*/
|
||||||
|
extern const char *const sudo_debug_priorities[];
|
||||||
|
extern const char *const sudo_debug_subsystems[];
|
||||||
|
|
||||||
|
void sudo_debug_enter(const char *func, const char *file, int line, int subsys);
|
||||||
|
void sudo_debug_exit(const char *func, const char *file, int line, int subsys);
|
||||||
|
void sudo_debug_exit_int(const char *func, const char *file, int line, int subsys, int rval);
|
||||||
|
void sudo_debug_exit_long(const char *func, const char *file, int line, int subsys, long rval);
|
||||||
|
void sudo_debug_exit_size_t(const char *func, const char *file, int line, int subsys, size_t rval);
|
||||||
|
void sudo_debug_exit_bool(const char *func, const char *file, int line, int subsys, int rval);
|
||||||
|
void sudo_debug_exit_str(const char *func, const char *file, int line, int subsys, const char *rval);
|
||||||
|
void sudo_debug_exit_str_masked(const char *func, const char *file, int line, int subsys, const char *rval);
|
||||||
|
void sudo_debug_exit_ptr(const char *func, const char *file, int line, int subsys, const void *rval);
|
||||||
|
int sudo_debug_init(const char *debugfile, const char *settings);
|
||||||
|
void sudo_debug_printf2(int level, const char *format, ...) __printflike(2, 3);
|
||||||
|
void sudo_debug_write(const char *str, int len);
|
||||||
|
void sudo_debug_execve2(int level, const char *path, char *const argv[], char *const envp[]);
|
||||||
|
|
||||||
|
#endif /* _SUDO_DEBUG_H */
|
@@ -40,6 +40,7 @@ struct sudo_conv_message {
|
|||||||
#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
|
#define SUDO_CONV_ERROR_MSG 0x0003 /* error message */
|
||||||
#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
|
#define SUDO_CONV_INFO_MSG 0x0004 /* informational message */
|
||||||
#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
|
#define SUDO_CONV_PROMPT_MASK 0x0005 /* mask user input */
|
||||||
|
#define SUDO_CONV_DEBUG_MSG 0x0006 /* debugging message */
|
||||||
#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
|
#define SUDO_CONV_PROMPT_ECHO_OK 0x1000 /* flag: allow echo if no tty */
|
||||||
int msg_type;
|
int msg_type;
|
||||||
int timeout;
|
int timeout;
|
||||||
|
@@ -47,6 +47,7 @@
|
|||||||
|
|
||||||
#include "sudo.h"
|
#include "sudo.h"
|
||||||
#include "sudo_plugin.h"
|
#include "sudo_plugin.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
|
||||||
extern int tgetpass_flags; /* XXX */
|
extern int tgetpass_flags; /* XXX */
|
||||||
|
|
||||||
@@ -91,6 +92,10 @@ sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
|||||||
if (msg->msg)
|
if (msg->msg)
|
||||||
(void) fputs(msg->msg, stderr);
|
(void) fputs(msg->msg, stderr);
|
||||||
break;
|
break;
|
||||||
|
case SUDO_CONV_DEBUG_MSG:
|
||||||
|
if (msg->msg)
|
||||||
|
sudo_debug_write(msg->msg, strlen(msg->msg));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@@ -42,11 +42,13 @@
|
|||||||
#else
|
#else
|
||||||
# include "compat/dlfcn.h"
|
# include "compat/dlfcn.h"
|
||||||
#endif
|
#endif
|
||||||
|
#include <ctype.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "sudo.h"
|
#include "sudo.h"
|
||||||
#include "sudo_plugin.h"
|
#include "sudo_plugin.h"
|
||||||
#include "sudo_plugin_int.h"
|
#include "sudo_plugin_int.h"
|
||||||
|
#include "sudo_debug.h"
|
||||||
|
|
||||||
#ifndef RTLD_GLOBAL
|
#ifndef RTLD_GLOBAL
|
||||||
# define RTLD_GLOBAL 0
|
# define RTLD_GLOBAL 0
|
||||||
@@ -56,19 +58,130 @@
|
|||||||
const char *noexec_path = _PATH_SUDO_NOEXEC;
|
const char *noexec_path = _PATH_SUDO_NOEXEC;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* XXX - for parse_args() */
|
||||||
|
const char *debug_file;
|
||||||
|
const char *debug_flags;
|
||||||
|
|
||||||
|
struct sudo_conf_table {
|
||||||
|
const char *name;
|
||||||
|
unsigned int namelen;
|
||||||
|
int (*setter)(const char *entry, void *data);
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sudo_conf_paths {
|
||||||
|
const char *pname;
|
||||||
|
unsigned int pnamelen;
|
||||||
|
const char **pval;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int set_debug(const char *entry, void *data);
|
||||||
|
static int set_path(const char *entry, void *data);
|
||||||
|
static int set_plugin(const char *entry, void *data);
|
||||||
|
|
||||||
|
static struct plugin_info_list plugin_info_list;
|
||||||
|
|
||||||
|
static struct sudo_conf_table sudo_conf_table[] = {
|
||||||
|
{ "Debug", sizeof("Debug") - 1, set_debug },
|
||||||
|
{ "Path", sizeof("Path") - 1, set_path },
|
||||||
|
{ "Plugin", sizeof("Plugin") - 1, set_plugin },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct sudo_conf_paths sudo_conf_paths[] = {
|
||||||
|
{ "askpass", sizeof("askpass"), &askpass_path },
|
||||||
|
#ifdef _PATH_SUDO_NOEXEC
|
||||||
|
{ "noexec", sizeof("noexec"), &noexec_path },
|
||||||
|
#endif
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_debug(const char *entry, void *data)
|
||||||
|
{
|
||||||
|
size_t filelen;
|
||||||
|
|
||||||
|
/* Parse Debug line */
|
||||||
|
debug_flags = strpbrk(entry, " \t");
|
||||||
|
if (debug_flags == NULL)
|
||||||
|
return FALSE;
|
||||||
|
filelen = (size_t)(debug_flags - entry);
|
||||||
|
while (isblank((unsigned char)*debug_flags))
|
||||||
|
debug_flags++;
|
||||||
|
|
||||||
|
/* Set debug file and parse the flags. */
|
||||||
|
debug_file = estrndup(entry, filelen);
|
||||||
|
debug_flags = estrdup(debug_flags);
|
||||||
|
sudo_debug_init(debug_file, debug_flags);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_path(const char *entry, void *data)
|
||||||
|
{
|
||||||
|
const char *name, *path;
|
||||||
|
struct sudo_conf_paths *cur;
|
||||||
|
|
||||||
|
/* Parse Path line */
|
||||||
|
name = entry;
|
||||||
|
path = strpbrk(entry, " \t");
|
||||||
|
if (path == NULL)
|
||||||
|
return FALSE;
|
||||||
|
while (isblank((unsigned char)*path))
|
||||||
|
path++;
|
||||||
|
|
||||||
|
/* Match supported paths, ignore the rest. */
|
||||||
|
for (cur = sudo_conf_paths; cur->pname != NULL; cur++) {
|
||||||
|
if (strncasecmp(name, cur->pname, cur->pnamelen) == 0 &&
|
||||||
|
isblank((unsigned char)name[cur->pnamelen])) {
|
||||||
|
*(cur->pval) = estrdup(path);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
set_plugin(const char *entry, void *data)
|
||||||
|
{
|
||||||
|
struct plugin_info_list *pil = data;
|
||||||
|
struct plugin_info *info;
|
||||||
|
const char *name, *path;
|
||||||
|
size_t namelen;
|
||||||
|
|
||||||
|
/* Parse Plugin line */
|
||||||
|
name = entry;
|
||||||
|
path = strpbrk(entry, " \t");
|
||||||
|
if (path == NULL)
|
||||||
|
return FALSE;
|
||||||
|
namelen = (size_t)(path - name);
|
||||||
|
while (isblank((unsigned char)*path))
|
||||||
|
path++;
|
||||||
|
|
||||||
|
info = emalloc(sizeof(*info));
|
||||||
|
info->symbol_name = estrndup(name, namelen);
|
||||||
|
info->path = estrdup(path);
|
||||||
|
info->prev = info;
|
||||||
|
info->next = NULL;
|
||||||
|
tq_append(pil, info);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read in /etc/sudo.conf
|
* Reads in /etc/sudo.conf
|
||||||
* Returns a list of plugins.
|
* Returns a list of plugins.
|
||||||
*/
|
*/
|
||||||
static struct plugin_info_list *
|
void
|
||||||
sudo_read_conf(const char *conf_file)
|
sudo_read_conf(void)
|
||||||
{
|
{
|
||||||
FILE *fp;
|
struct sudo_conf_table *cur;
|
||||||
char *cp, *name, *path;
|
|
||||||
struct plugin_info *info;
|
struct plugin_info *info;
|
||||||
static struct plugin_info_list pil; /* XXX */
|
FILE *fp;
|
||||||
|
char *cp;
|
||||||
|
|
||||||
if ((fp = fopen(conf_file, "r")) == NULL)
|
if ((fp = fopen(_PATH_SUDO_CONF, "r")) == NULL)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
while ((cp = sudo_parseln(fp)) != NULL) {
|
while ((cp = sudo_parseln(fp)) != NULL) {
|
||||||
@@ -76,49 +189,28 @@ sudo_read_conf(const char *conf_file)
|
|||||||
if (*cp == '\0')
|
if (*cp == '\0')
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Look for a line starting with "Path" */
|
for (cur = sudo_conf_table; cur->name != NULL; cur++) {
|
||||||
if (strncasecmp(cp, "Path", 4) == 0) {
|
if (strncasecmp(cp, cur->name, cur->namelen) == 0 &&
|
||||||
/* Parse line */
|
isblank((unsigned char)cp[cur->namelen])) {
|
||||||
if ((name = strtok(cp + 4, " \t")) == NULL ||
|
cp += cur->namelen;
|
||||||
(path = strtok(NULL, " \t")) == NULL) {
|
while (isblank((unsigned char)*cp))
|
||||||
continue;
|
cp++;
|
||||||
|
if (cur->setter(cp, &plugin_info_list))
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
if (strcasecmp(name, "askpass") == 0)
|
|
||||||
askpass_path = estrdup(path);
|
|
||||||
#ifdef _PATH_SUDO_NOEXEC
|
|
||||||
else if (strcasecmp(name, "noexec") == 0)
|
|
||||||
noexec_path = estrdup(path);
|
|
||||||
#endif
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look for a line starting with "Plugin" */
|
|
||||||
if (strncasecmp(cp, "Plugin", 6) == 0) {
|
|
||||||
/* Parse line */
|
|
||||||
if ((name = strtok(cp + 6, " \t")) == NULL ||
|
|
||||||
(path = strtok(NULL, " \t")) == NULL) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
info = emalloc(sizeof(*info));
|
|
||||||
info->symbol_name = estrdup(name);
|
|
||||||
info->path = estrdup(path);
|
|
||||||
info->prev = info;
|
|
||||||
info->next = NULL;
|
|
||||||
tq_append(&pil, info);
|
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
|
|
||||||
done:
|
done:
|
||||||
if (tq_empty(&pil)) {
|
if (tq_empty(&plugin_info_list)) {
|
||||||
/* Default policy plugin */
|
/* Default policy plugin */
|
||||||
info = emalloc(sizeof(*info));
|
info = emalloc(sizeof(*info));
|
||||||
info->symbol_name = "sudoers_policy";
|
info->symbol_name = "sudoers_policy";
|
||||||
info->path = SUDOERS_PLUGIN;
|
info->path = SUDOERS_PLUGIN;
|
||||||
info->prev = info;
|
info->prev = info;
|
||||||
info->next = NULL;
|
info->next = NULL;
|
||||||
tq_append(&pil, info);
|
tq_append(&plugin_info_list, info);
|
||||||
|
|
||||||
/* Default I/O plugin */
|
/* Default I/O plugin */
|
||||||
info = emalloc(sizeof(*info));
|
info = emalloc(sizeof(*info));
|
||||||
@@ -126,33 +218,27 @@ done:
|
|||||||
info->path = SUDOERS_PLUGIN;
|
info->path = SUDOERS_PLUGIN;
|
||||||
info->prev = info;
|
info->prev = info;
|
||||||
info->next = NULL;
|
info->next = NULL;
|
||||||
tq_append(&pil, info);
|
tq_append(&plugin_info_list, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
return &pil;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Load the plugins listed in conf_file.
|
* Load the plugins listed in sudo.conf.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
sudo_load_plugins(const char *conf_file,
|
sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||||
struct plugin_container *policy_plugin,
|
|
||||||
struct plugin_container_list *io_plugins)
|
struct plugin_container_list *io_plugins)
|
||||||
{
|
{
|
||||||
struct generic_plugin *plugin;
|
struct generic_plugin *plugin;
|
||||||
struct plugin_container *container;
|
struct plugin_container *container;
|
||||||
struct plugin_info *info;
|
struct plugin_info *info;
|
||||||
struct plugin_info_list *plugin_list;
|
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
void *handle;
|
void *handle;
|
||||||
char path[PATH_MAX];
|
char path[PATH_MAX];
|
||||||
int rval = FALSE;
|
int rval = FALSE;
|
||||||
|
|
||||||
/* Parse sudo.conf */
|
/* Walk plugin list. */
|
||||||
plugin_list = sudo_read_conf(conf_file);
|
tq_foreach_fwd(&plugin_info_list, info) {
|
||||||
|
|
||||||
tq_foreach_fwd(plugin_list, info) {
|
|
||||||
if (info->path[0] == '/') {
|
if (info->path[0] == '/') {
|
||||||
if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) {
|
if (strlcpy(path, info->path, sizeof(path)) >= sizeof(path)) {
|
||||||
warningx(_("%s: %s"), info->path, strerror(ENAMETOOLONG));
|
warningx(_("%s: %s"), info->path, strerror(ENAMETOOLONG));
|
||||||
@@ -205,7 +291,7 @@ sudo_load_plugins(const char *conf_file,
|
|||||||
if (plugin->type == SUDO_POLICY_PLUGIN) {
|
if (plugin->type == SUDO_POLICY_PLUGIN) {
|
||||||
if (policy_plugin->handle) {
|
if (policy_plugin->handle) {
|
||||||
warningx(_("%s: only a single policy plugin may be loaded"),
|
warningx(_("%s: only a single policy plugin may be loaded"),
|
||||||
conf_file);
|
_PATH_SUDO_CONF);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
policy_plugin->handle = handle;
|
policy_plugin->handle = handle;
|
||||||
@@ -223,7 +309,7 @@ sudo_load_plugins(const char *conf_file,
|
|||||||
}
|
}
|
||||||
if (policy_plugin->handle == NULL) {
|
if (policy_plugin->handle == NULL) {
|
||||||
warningx(_("%s: at least one policy plugin must be specified"),
|
warningx(_("%s: at least one policy plugin must be specified"),
|
||||||
conf_file);
|
_PATH_SUDO_CONF);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
if (policy_plugin->u.policy->check_policy == NULL) {
|
if (policy_plugin->u.policy->check_policy == NULL) {
|
||||||
|
@@ -53,6 +53,10 @@
|
|||||||
extern char *optarg;
|
extern char *optarg;
|
||||||
extern int optind;
|
extern int optind;
|
||||||
|
|
||||||
|
/* XXX */
|
||||||
|
extern const char *debug_file;
|
||||||
|
extern const char *debug_flags;
|
||||||
|
|
||||||
int tgetpass_flags;
|
int tgetpass_flags;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -72,43 +76,47 @@ static struct sudo_settings {
|
|||||||
{ "bsdauth_type" },
|
{ "bsdauth_type" },
|
||||||
#define ARG_LOGIN_CLASS 1
|
#define ARG_LOGIN_CLASS 1
|
||||||
{ "login_class" },
|
{ "login_class" },
|
||||||
#define ARG_DEBUG_LEVEL 2
|
#define ARG_DEBUG_FILE 2
|
||||||
|
{ "debug_file" },
|
||||||
|
#define ARG_DEBUG_FLAGS 3
|
||||||
|
{ "debug_flags" },
|
||||||
|
#define ARG_DEBUG_LEVEL 4
|
||||||
{ "debug_level" },
|
{ "debug_level" },
|
||||||
#define ARG_PRESERVE_ENVIRONMENT 3
|
#define ARG_PRESERVE_ENVIRONMENT 5
|
||||||
{ "preserve_environment" },
|
{ "preserve_environment" },
|
||||||
#define ARG_RUNAS_GROUP 4
|
#define ARG_RUNAS_GROUP 6
|
||||||
{ "runas_group" },
|
{ "runas_group" },
|
||||||
#define ARG_SET_HOME 5
|
#define ARG_SET_HOME 7
|
||||||
{ "set_home" },
|
{ "set_home" },
|
||||||
#define ARG_USER_SHELL 6
|
#define ARG_USER_SHELL 8
|
||||||
{ "run_shell" },
|
{ "run_shell" },
|
||||||
#define ARG_LOGIN_SHELL 7
|
#define ARG_LOGIN_SHELL 9
|
||||||
{ "login_shell" },
|
{ "login_shell" },
|
||||||
#define ARG_IGNORE_TICKET 8
|
#define ARG_IGNORE_TICKET 10
|
||||||
{ "ignore_ticket" },
|
{ "ignore_ticket" },
|
||||||
#define ARG_PROMPT 9
|
#define ARG_PROMPT 11
|
||||||
{ "prompt" },
|
{ "prompt" },
|
||||||
#define ARG_SELINUX_ROLE 10
|
#define ARG_SELINUX_ROLE 12
|
||||||
{ "selinux_role" },
|
{ "selinux_role" },
|
||||||
#define ARG_SELINUX_TYPE 11
|
#define ARG_SELINUX_TYPE 13
|
||||||
{ "selinux_type" },
|
{ "selinux_type" },
|
||||||
#define ARG_RUNAS_USER 12
|
#define ARG_RUNAS_USER 14
|
||||||
{ "runas_user" },
|
{ "runas_user" },
|
||||||
#define ARG_PROGNAME 13
|
#define ARG_PROGNAME 15
|
||||||
{ "progname" },
|
{ "progname" },
|
||||||
#define ARG_IMPLIED_SHELL 14
|
#define ARG_IMPLIED_SHELL 16
|
||||||
{ "implied_shell" },
|
{ "implied_shell" },
|
||||||
#define ARG_PRESERVE_GROUPS 15
|
#define ARG_PRESERVE_GROUPS 17
|
||||||
{ "preserve_groups" },
|
{ "preserve_groups" },
|
||||||
#define ARG_NONINTERACTIVE 16
|
#define ARG_NONINTERACTIVE 18
|
||||||
{ "noninteractive" },
|
{ "noninteractive" },
|
||||||
#define ARG_SUDOEDIT 17
|
#define ARG_SUDOEDIT 19
|
||||||
{ "sudoedit" },
|
{ "sudoedit" },
|
||||||
#define ARG_CLOSEFROM 18
|
#define ARG_CLOSEFROM 20
|
||||||
{ "closefrom" },
|
{ "closefrom" },
|
||||||
#define ARG_NET_ADDRS 19
|
#define ARG_NET_ADDRS 21
|
||||||
{ "network_addrs" },
|
{ "network_addrs" },
|
||||||
#define NUM_SETTINGS 20
|
#define NUM_SETTINGS 22
|
||||||
{ NULL }
|
{ NULL }
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -144,6 +152,12 @@ parse_args(int argc, char **argv, int *nargc, char ***nargv, char ***settingsp,
|
|||||||
if (get_net_ifs(&cp) > 0)
|
if (get_net_ifs(&cp) > 0)
|
||||||
sudo_settings[ARG_NET_ADDRS].value = cp;
|
sudo_settings[ARG_NET_ADDRS].value = cp;
|
||||||
|
|
||||||
|
/* Set debug file and flags from sudo.conf. */
|
||||||
|
if (debug_file != NULL)
|
||||||
|
sudo_settings[ARG_DEBUG_FILE].value = debug_file;
|
||||||
|
if (debug_flags != NULL)
|
||||||
|
sudo_settings[ARG_DEBUG_FLAGS].value = debug_flags;
|
||||||
|
|
||||||
/* Returns true if the last option string was "--" */
|
/* Returns true if the last option string was "--" */
|
||||||
#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \
|
#define got_end_of_args (optind > 1 && argv[optind - 1][0] == '-' && \
|
||||||
argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
|
argv[optind - 1][1] == '-' && argv[optind - 1][2] == '\0')
|
||||||
|
@@ -200,6 +200,9 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
memset(&user_details, 0, sizeof(user_details));
|
memset(&user_details, 0, sizeof(user_details));
|
||||||
user_info = get_user_info(&user_details);
|
user_info = get_user_info(&user_details);
|
||||||
|
|
||||||
|
/* Read sudo.conf. */
|
||||||
|
sudo_read_conf();
|
||||||
|
|
||||||
/* Parse command line arguments. */
|
/* Parse command line arguments. */
|
||||||
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
|
sudo_mode = parse_args(argc, argv, &nargc, &nargv, &settings, &env_add);
|
||||||
sudo_debug(9, "sudo_mode %d", sudo_mode);
|
sudo_debug(9, "sudo_mode %d", sudo_mode);
|
||||||
@@ -211,8 +214,8 @@ main(int argc, char *argv[], char *envp[])
|
|||||||
(void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
|
(void) printf(_("Configure options: %s\n"), CONFIGURE_ARGS);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read sudo.conf and load plugins. */
|
/* Load plugins. */
|
||||||
if (!sudo_load_plugins(_PATH_SUDO_CONF, &policy_plugin, &io_plugins))
|
if (!sudo_load_plugins(&policy_plugin, &io_plugins))
|
||||||
errorx(1, _("fatal error, unable to load plugins"));
|
errorx(1, _("fatal error, unable to load plugins"));
|
||||||
|
|
||||||
/* Open policy plugin. */
|
/* Open policy plugin. */
|
||||||
|
@@ -78,8 +78,8 @@ int sudo_conversation(int num_msgs, const struct sudo_conv_message msgs[],
|
|||||||
struct sudo_conv_reply replies[]);
|
struct sudo_conv_reply replies[]);
|
||||||
int _sudo_printf(int msg_type, const char *fmt, ...);
|
int _sudo_printf(int msg_type, const char *fmt, ...);
|
||||||
|
|
||||||
int sudo_load_plugins(const char *conf_file,
|
void sudo_read_conf(void);
|
||||||
struct plugin_container *policy_plugin,
|
int sudo_load_plugins(struct plugin_container *policy_plugin,
|
||||||
struct plugin_container_list *io_plugins);
|
struct plugin_container_list *io_plugins);
|
||||||
|
|
||||||
#endif /* _SUDO_PLUGIN_INT_H */
|
#endif /* _SUDO_PLUGIN_INT_H */
|
||||||
|
Reference in New Issue
Block a user