2
0
mirror of https://github.com/sudo-project/sudo.git synced 2025-08-28 12:57:50 +00:00

Enable debugging via sudo.conf.

This commit is contained in:
Todd C. Miller 2012-01-06 10:58:13 -05:00
parent baa9273dd5
commit 38526ca149

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 1996, 1998-2005, 2007-2011 * Copyright (c) 1996, 1998-2005, 2007-2012
* Todd C. Miller <Todd.Miller@courtesan.com> * Todd C. Miller <Todd.Miller@courtesan.com>
* *
* Permission to use, copy, modify, and distribute this software for any * Permission to use, copy, modify, and distribute this software for any
@ -75,14 +75,13 @@
# include <locale.h> # include <locale.h>
#endif #endif
#define SUDO_ERROR_WRAP 0 /* XXX */
#include "sudoers.h" #include "sudoers.h"
#include "interfaces.h" #include "interfaces.h"
#include "parse.h" #include "parse.h"
#include "redblack.h" #include "redblack.h"
#include "gettext.h" #include "gettext.h"
#include "sudoers_version.h" #include "sudoers_version.h"
#include "sudo_conf.h"
#include <gram.h> #include <gram.h>
struct sudoersfile { struct sudoersfile {
@ -104,13 +103,13 @@ static void quit(int);
static char *get_args(char *); static char *get_args(char *);
static char *get_editor(char **); static char *get_editor(char **);
static void get_hostname(void); static void get_hostname(void);
static char whatnow(void); static int whatnow(void);
static int check_aliases(bool, bool); static int check_aliases(bool, bool);
static bool check_syntax(char *, bool, bool); static bool check_syntax(char *, bool, bool);
static bool edit_sudoers(struct sudoersfile *, char *, char *, int); static bool edit_sudoers(struct sudoersfile *, char *, char *, int);
static bool install_sudoers(struct sudoersfile *, bool); static bool install_sudoers(struct sudoersfile *, bool);
static int print_unused(void *, void *); static int print_unused(void *, void *);
static bool reparse_sudoers(char *, char *, bool, bool); static void reparse_sudoers(char *, char *, bool, bool);
static int run_command(char *, char **); static int run_command(char *, char **);
static int visudo_printf(int msg_type, const char *fmt, ...); static int visudo_printf(int msg_type, const char *fmt, ...);
static void setup_signals(void); static void setup_signals(void);
@ -150,11 +149,15 @@ main(int argc, char *argv[])
{ {
struct sudoersfile *sp; struct sudoersfile *sp;
char *args, *editor, *sudoers_path; char *args, *editor, *sudoers_path;
int ch; int ch, exitcode = 0;
bool quiet, strict, oldperms; bool quiet, strict, oldperms;
debug_decl(main, SUDO_DEBUG_MAIN)
#if defined(SUDO_DEVEL) && defined(__OpenBSD__) #if defined(SUDO_DEVEL) && defined(__OpenBSD__)
extern char *malloc_options; {
malloc_options = "AFGJPR"; extern char *malloc_options;
malloc_options = "AFGJPR";
}
#endif #endif
#if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME) #if !defined(HAVE_GETPROGNAME) && !defined(HAVE___PROGNAME)
@ -170,6 +173,9 @@ main(int argc, char *argv[])
if (argc < 1) if (argc < 1)
usage(1); usage(1);
/* Read sudo.conf. */
sudo_conf_read();
/* /*
* Arg handling. * Arg handling.
*/ */
@ -180,7 +186,7 @@ main(int argc, char *argv[])
case 'V': case 'V':
(void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION); (void) printf(_("%s version %s\n"), getprogname(), PACKAGE_VERSION);
(void) printf(_("%s grammar version %d\n"), getprogname(), SUDOERS_GRAMMAR_VERSION); (void) printf(_("%s grammar version %d\n"), getprogname(), SUDOERS_GRAMMAR_VERSION);
exit(0); goto done;
case 'c': case 'c':
checkonly++; /* check mode */ checkonly++; /* check mode */
break; break;
@ -218,8 +224,10 @@ main(int argc, char *argv[])
/* Setup defaults data structures. */ /* Setup defaults data structures. */
init_defaults(); init_defaults();
if (checkonly) if (checkonly) {
exit(check_syntax(sudoers_path, quiet, strict) ? 1 : 0); exitcode = check_syntax(sudoers_path, quiet, strict) ? 0 : 1;
goto done;
}
/* /*
* Parse the existing sudoers file(s) in quiet mode to highlight any * Parse the existing sudoers file(s) in quiet mode to highlight any
@ -257,7 +265,9 @@ main(int argc, char *argv[])
(void) install_sudoers(sp, oldperms); (void) install_sudoers(sp, oldperms);
} }
exit(0); done:
sudo_debug_exit_int(__func__, __FILE__, __LINE__, sudo_debug_subsys, exitcode);
exit(exitcode);
} }
/* /*
@ -303,6 +313,8 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
off_t orig_size; /* starting size of sudoers file */ off_t orig_size; /* starting size of sudoers file */
ssize_t nread; /* number of bytes read */ ssize_t nread; /* number of bytes read */
struct stat sb; /* stat buffer */ struct stat sb; /* stat buffer */
bool rval = false; /* return value */
debug_decl(edit_sudoers, SUDO_DEBUG_UTIL)
if (fstat(sp->fd, &sb) == -1) if (fstat(sp->fd, &sb) == -1)
error(1, _("unable to stat %s"), sp->path); error(1, _("unable to stat %s"), sp->path);
@ -411,17 +423,17 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
if (stat(sp->tpath, &sb) < 0) { if (stat(sp->tpath, &sb) < 0) {
warningx(_("unable to stat temporary file (%s), %s unchanged"), warningx(_("unable to stat temporary file (%s), %s unchanged"),
sp->tpath, sp->path); sp->tpath, sp->path);
return false; goto done;
} }
if (sb.st_size == 0 && orig_size != 0) { if (sb.st_size == 0 && orig_size != 0) {
warningx(_("zero length temporary file (%s), %s unchanged"), warningx(_("zero length temporary file (%s), %s unchanged"),
sp->tpath, sp->path); sp->tpath, sp->path);
sp->modified = true; sp->modified = true;
return false; goto done;
} }
} else { } else {
warningx(_("editor (%s) failed, %s unchanged"), editor, sp->path); warningx(_("editor (%s) failed, %s unchanged"), editor, sp->path);
return false; goto done;
} }
/* Set modified bit if use changed the file. */ /* Set modified bit if use changed the file. */
@ -445,19 +457,21 @@ edit_sudoers(struct sudoersfile *sp, char *editor, char *args, int lineno)
else else
warningx(_("%s unchanged"), sp->tpath); warningx(_("%s unchanged"), sp->tpath);
return true; rval = true;
done:
debug_return_bool(rval);
} }
/* /*
* Parse sudoers after editing and re-edit any ones that caused a parse error. * Parse sudoers after editing and re-edit any ones that caused a parse error.
* Returns true on success, else false.
*/ */
static bool static void
reparse_sudoers(char *editor, char *args, bool strict, bool quiet) reparse_sudoers(char *editor, char *args, bool strict, bool quiet)
{ {
struct sudoersfile *sp, *last; struct sudoersfile *sp, *last;
FILE *fp; FILE *fp;
int ch; int ch;
debug_decl(reparse_sudoers, SUDO_DEBUG_UTIL)
/* /*
* Parse the edited sudoers files and do sanity checking * Parse the edited sudoers files and do sanity checking
@ -498,7 +512,10 @@ reparse_sudoers(char *editor, char *args, bool strict, bool quiet)
switch (whatnow()) { switch (whatnow()) {
case 'Q' : parse_error = false; /* ignore parse error */ case 'Q' : parse_error = false; /* ignore parse error */
break; break;
case 'x' : cleanup(0); case 'x' : /* XXX - should return instead of exiting */
cleanup(0);
sudo_debug_exit_int(__func__, __FILE__,
__LINE__, sudo_debug_subsys, 0);
exit(0); exit(0);
break; break;
} }
@ -526,7 +543,7 @@ reparse_sudoers(char *editor, char *args, bool strict, bool quiet)
} }
} while (parse_error); } while (parse_error);
return true; debug_return;
} }
/* /*
@ -537,6 +554,8 @@ static bool
install_sudoers(struct sudoersfile *sp, bool oldperms) install_sudoers(struct sudoersfile *sp, bool oldperms)
{ {
struct stat sb; struct stat sb;
bool rval = false;
debug_decl(install_sudoers, SUDO_DEBUG_UTIL)
if (!sp->modified) { if (!sp->modified) {
/* /*
@ -549,7 +568,8 @@ install_sudoers(struct sudoersfile *sp, bool oldperms)
if ((sb.st_mode & 0777) != SUDOERS_MODE) if ((sb.st_mode & 0777) != SUDOERS_MODE)
(void) chmod(sp->path, SUDOERS_MODE); (void) chmod(sp->path, SUDOERS_MODE);
} }
return true; rval = true;
goto done;
} }
/* /*
@ -572,12 +592,12 @@ install_sudoers(struct sudoersfile *sp, bool oldperms)
if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) { if (chown(sp->tpath, SUDOERS_UID, SUDOERS_GID) != 0) {
warning(_("unable to set (uid, gid) of %s to (%u, %u)"), warning(_("unable to set (uid, gid) of %s to (%u, %u)"),
sp->tpath, SUDOERS_UID, SUDOERS_GID); sp->tpath, SUDOERS_UID, SUDOERS_GID);
return false; goto done;
} }
if (chmod(sp->tpath, SUDOERS_MODE) != 0) { if (chmod(sp->tpath, SUDOERS_MODE) != 0) {
warning(_("unable to change mode of %s to 0%o"), sp->tpath, warning(_("unable to change mode of %s to 0%o"), sp->tpath,
SUDOERS_MODE); SUDOERS_MODE);
return false; goto done;
} }
} }
@ -611,17 +631,19 @@ install_sudoers(struct sudoersfile *sp, bool oldperms)
(void) unlink(sp->tpath); (void) unlink(sp->tpath);
efree(sp->tpath); efree(sp->tpath);
sp->tpath = NULL; sp->tpath = NULL;
return false; goto done;
} }
efree(sp->tpath); efree(sp->tpath);
sp->tpath = NULL; sp->tpath = NULL;
} else { } else {
warning(_("error renaming %s, %s unchanged"), sp->tpath, sp->path); warning(_("error renaming %s, %s unchanged"), sp->tpath, sp->path);
(void) unlink(sp->tpath); (void) unlink(sp->tpath);
return false; goto done;
} }
} }
return true; rval = true;
done:
debug_return_bool(rval);
} }
/* STUB */ /* STUB */
@ -670,10 +692,11 @@ group_plugin_query(const char *user, const char *group, const struct passwd *pw)
* Assuming a parse error occurred, prompt the user for what they want * Assuming a parse error occurred, prompt the user for what they want
* to do now. Returns the first letter of their choice. * to do now. Returns the first letter of their choice.
*/ */
static char static int
whatnow(void) whatnow(void)
{ {
int choice, c; int choice, c;
debug_decl(whatnow, SUDO_DEBUG_UTIL)
for (;;) { for (;;) {
(void) fputs(_("What now? "), stdout); (void) fputs(_("What now? "), stdout);
@ -688,7 +711,7 @@ whatnow(void)
case 'e': case 'e':
case 'x': case 'x':
case 'Q': case 'Q':
return choice; debug_return_int(choice);
default: default:
(void) puts(_("Options are:\n" (void) puts(_("Options are:\n"
" (e)dit sudoers file again\n" " (e)dit sudoers file again\n"
@ -704,19 +727,22 @@ whatnow(void)
static void static void
setup_signals(void) setup_signals(void)
{ {
sigaction_t sa; sigaction_t sa;
debug_decl(setup_signals, SUDO_DEBUG_UTIL)
/* /*
* Setup signal handlers to cleanup nicely. * Setup signal handlers to cleanup nicely.
*/ */
zero_bytes(&sa, sizeof(sa)); zero_bytes(&sa, sizeof(sa));
sigemptyset(&sa.sa_mask); sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART; sa.sa_flags = SA_RESTART;
sa.sa_handler = quit; sa.sa_handler = quit;
(void) sigaction(SIGTERM, &sa, NULL); (void) sigaction(SIGTERM, &sa, NULL);
(void) sigaction(SIGHUP, &sa, NULL); (void) sigaction(SIGHUP, &sa, NULL);
(void) sigaction(SIGINT, &sa, NULL); (void) sigaction(SIGINT, &sa, NULL);
(void) sigaction(SIGQUIT, &sa, NULL); (void) sigaction(SIGQUIT, &sa, NULL);
debug_return;
} }
static int static int
@ -724,6 +750,7 @@ run_command(char *path, char **argv)
{ {
int status; int status;
pid_t pid, rv; pid_t pid, rv;
debug_decl(run_command, SUDO_DEBUG_UTIL)
switch (pid = fork()) { switch (pid = fork()) {
case -1: case -1:
@ -743,16 +770,17 @@ run_command(char *path, char **argv)
rv = waitpid(pid, &status, 0); rv = waitpid(pid, &status, 0);
} while (rv == -1 && errno == EINTR); } while (rv == -1 && errno == EINTR);
if (rv == -1 || !WIFEXITED(status)) if (rv != -1)
return -1; rv = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
return WEXITSTATUS(status); debug_return_int(rv);
} }
static bool static bool
check_syntax(char *sudoers_path, bool quiet, bool strict) check_syntax(char *sudoers_path, bool quiet, bool strict)
{ {
struct stat sb; struct stat sb;
bool rval; bool ok = false;
debug_decl(check_syntax, SUDO_DEBUG_UTIL)
if (strcmp(sudoers_path, "-") == 0) { if (strcmp(sudoers_path, "-") == 0) {
yyin = stdin; yyin = stdin;
@ -760,7 +788,7 @@ check_syntax(char *sudoers_path, bool quiet, bool strict)
} else if ((yyin = fopen(sudoers_path, "r")) == NULL) { } else if ((yyin = fopen(sudoers_path, "r")) == NULL) {
if (!quiet) if (!quiet)
warning(_("unable to open %s"), sudoers_path); warning(_("unable to open %s"), sudoers_path);
exit(1); goto done;
} }
init_parser(sudoers_path, quiet); init_parser(sudoers_path, quiet);
if (yyparse() && !parse_error) { if (yyparse() && !parse_error) {
@ -773,7 +801,7 @@ check_syntax(char *sudoers_path, bool quiet, bool strict)
parse_error = true; parse_error = true;
errorfile = sudoers_path; errorfile = sudoers_path;
} }
rval = parse_error; ok = !parse_error;
if (!quiet) { if (!quiet) {
if (parse_error) { if (parse_error) {
if (errorlineno != -1) if (errorlineno != -1)
@ -788,7 +816,7 @@ check_syntax(char *sudoers_path, bool quiet, bool strict)
/* Check mode and owner in strict mode. */ /* Check mode and owner in strict mode. */
if (strict && yyin != stdin && fstat(fileno(yyin), &sb) == 0) { if (strict && yyin != stdin && fstat(fileno(yyin), &sb) == 0) {
if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID) { if (sb.st_uid != SUDOERS_UID || sb.st_gid != SUDOERS_GID) {
rval = true; ok = false;
if (!quiet) { if (!quiet) {
fprintf(stderr, fprintf(stderr,
_("%s: wrong owner (uid, gid) should be (%u, %u)\n"), _("%s: wrong owner (uid, gid) should be (%u, %u)\n"),
@ -796,7 +824,7 @@ check_syntax(char *sudoers_path, bool quiet, bool strict)
} }
} }
if ((sb.st_mode & 07777) != SUDOERS_MODE) { if ((sb.st_mode & 07777) != SUDOERS_MODE) {
rval = true; ok = false;
if (!quiet) { if (!quiet) {
fprintf(stderr, _("%s: bad permissions, should be mode 0%o\n"), fprintf(stderr, _("%s: bad permissions, should be mode 0%o\n"),
sudoers_path, SUDOERS_MODE); sudoers_path, SUDOERS_MODE);
@ -804,7 +832,8 @@ check_syntax(char *sudoers_path, bool quiet, bool strict)
} }
} }
return rval; done:
debug_return_bool(ok);
} }
/* /*
@ -817,6 +846,7 @@ open_sudoers(const char *path, bool doedit, bool *keepopen)
struct sudoersfile *entry; struct sudoersfile *entry;
FILE *fp; FILE *fp;
int open_flags; int open_flags;
debug_decl(open_sudoers, SUDO_DEBUG_UTIL)
if (checkonly) if (checkonly)
open_flags = O_RDONLY; open_flags = O_RDONLY;
@ -840,7 +870,7 @@ open_sudoers(const char *path, bool doedit, bool *keepopen)
if (entry->fd == -1) { if (entry->fd == -1) {
warning("%s", entry->path); warning("%s", entry->path);
efree(entry); efree(entry);
return NULL; debug_return_ptr(NULL);
} }
if (!checkonly && !lock_file(entry->fd, SUDO_TLOCK)) if (!checkonly && !lock_file(entry->fd, SUDO_TLOCK))
errorx(1, _("%s busy, try again later"), entry->path); errorx(1, _("%s busy, try again later"), entry->path);
@ -860,13 +890,14 @@ open_sudoers(const char *path, bool doedit, bool *keepopen)
} }
if (keepopen != NULL) if (keepopen != NULL)
*keepopen = true; *keepopen = true;
return fp; debug_return_ptr(fp);
} }
static char * static char *
get_editor(char **args) get_editor(char **args)
{ {
char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs; char *Editor, *EditorArgs, *EditorPath, *UserEditor, *UserEditorArgs;
debug_decl(get_editor, SUDO_DEBUG_UTIL)
/* /*
* Check VISUAL and EDITOR environment variables to see which editor * Check VISUAL and EDITOR environment variables to see which editor
@ -960,7 +991,7 @@ get_editor(char **args)
errorx(1, _("no editor found (editor path = %s)"), def_editor); errorx(1, _("no editor found (editor path = %s)"), def_editor);
} }
*args = EditorArgs; *args = EditorArgs;
return Editor; debug_return_str(Editor);
} }
/* /*
@ -970,6 +1001,7 @@ static char *
get_args(char *cmnd) get_args(char *cmnd)
{ {
char *args; char *args;
debug_decl(get_args, SUDO_DEBUG_UTIL)
args = cmnd; args = cmnd;
while (*args && !isblank((unsigned char) *args)) while (*args && !isblank((unsigned char) *args))
@ -979,7 +1011,7 @@ get_args(char *cmnd)
while (*args && isblank((unsigned char) *args)) while (*args && isblank((unsigned char) *args))
args++; args++;
} }
return *args ? args : NULL; debug_return_str(*args ? args : NULL);
} }
/* /*
@ -989,21 +1021,23 @@ static void
get_hostname(void) get_hostname(void)
{ {
char *p, thost[MAXHOSTNAMELEN + 1]; char *p, thost[MAXHOSTNAMELEN + 1];
debug_decl(get_hostname, SUDO_DEBUG_UTIL)
if (gethostname(thost, sizeof(thost)) != 0) { if (gethostname(thost, sizeof(thost)) != -1) {
user_host = user_shost = "localhost"; thost[sizeof(thost) - 1] = '\0';
return; user_host = estrdup(thost);
}
thost[sizeof(thost) - 1] = '\0';
user_host = estrdup(thost);
if ((p = strchr(user_host, '.'))) { if ((p = strchr(user_host, '.'))) {
*p = '\0'; *p = '\0';
user_shost = estrdup(user_host); user_shost = estrdup(user_host);
*p = '.'; *p = '.';
} else {
user_shost = user_host;
}
} else { } else {
user_shost = user_host; user_host = user_shost = "localhost";
} }
debug_return;
} }
static bool static bool
@ -1012,6 +1046,7 @@ alias_remove_recursive(char *name, int type)
struct member *m; struct member *m;
struct alias *a; struct alias *a;
bool rval = true; bool rval = true;
debug_decl(alias_remove_recursive, SUDO_DEBUG_UTIL)
if ((a = alias_find(name, type)) != NULL) { if ((a = alias_find(name, type)) != NULL) {
tq_foreach_fwd(&a->members, m) { tq_foreach_fwd(&a->members, m) {
@ -1025,7 +1060,7 @@ alias_remove_recursive(char *name, int type)
a = alias_remove(name, type); a = alias_remove(name, type);
if (a) if (a)
rbinsert(alias_freelist, a); rbinsert(alias_freelist, a);
return rval; debug_return_bool(rval);
} }
static int static int
@ -1034,6 +1069,7 @@ check_alias(char *name, int type, int strict, int quiet)
struct member *m; struct member *m;
struct alias *a; struct alias *a;
int errors = 0; int errors = 0;
debug_decl(check_alias, SUDO_DEBUG_UTIL)
if ((a = alias_find(name, type)) != NULL) { if ((a = alias_find(name, type)) != NULL) {
/* check alias contents */ /* check alias contents */
@ -1061,7 +1097,7 @@ check_alias(char *name, int type, int strict, int quiet)
errors++; errors++;
} }
return errors; debug_return_int(errors);
} }
/* /*
@ -1077,6 +1113,7 @@ check_aliases(bool strict, bool quiet)
struct userspec *us; struct userspec *us;
struct defaults *d; struct defaults *d;
int atype, errors = 0; int atype, errors = 0;
debug_decl(check_aliases, SUDO_DEBUG_UTIL)
alias_freelist = rbcreate(alias_compare); alias_freelist = rbcreate(alias_compare);
@ -1176,7 +1213,7 @@ check_aliases(bool strict, bool quiet)
if (!no_aliases() && !quiet) if (!no_aliases() && !quiet)
alias_apply(print_unused, strict ? "Error" : "Warning"); alias_apply(print_unused, strict ? "Error" : "Warning");
return strict ? errors : 0; debug_return_int(strict ? errors : 0);
} }
static int static int
@ -1185,7 +1222,7 @@ print_unused(void *v1, void *v2)
struct alias *a = (struct alias *)v1; struct alias *a = (struct alias *)v1;
char *prefix = (char *)v2; char *prefix = (char *)v2;
warningx(_("%s: unused %s_Alias %s"), prefix, warningx2(_("%s: unused %s_Alias %s"), prefix,
a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" : a->type == HOSTALIAS ? "Host" : a->type == CMNDALIAS ? "Cmnd" :
a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" : a->type == USERALIAS ? "User" : a->type == RUNASALIAS ? "Runas" :
"Unknown", a->name); "Unknown", a->name);