Add support for "Defaults" line in sudoers to make configuration variables
changable at runtime (and on a global, per-host and per-user basis). Both the names and the internal representation are still subject to change. It was necessary to make sudo_user.runas but a char ** instead of a char * since this value can be changed by a Defaults line. There is a similar (but more complicated) issue with sudo_user.prompt but it is handled differently at the moment. Add a "-L" flag to list the name of options with their descriptions. This may only be temporary. Move some prototypes to parse.h Be much less restrictive on what is allowed for a username.
This commit is contained in:
4
BUGS
4
BUGS
@@ -11,3 +11,7 @@ Known bugs in sudo version 1.6
|
||||
given. This is a flaw in GNU autoconf.
|
||||
|
||||
4) On DUNIX in sia mode, hitting return at the prompt does not quit.
|
||||
|
||||
5) In parse.lex, '@" should not need to be a special character.
|
||||
For some reason, if it is not excluded from WORD, Defaults@ doesn't
|
||||
match.
|
||||
|
10
INSTALL
10
INSTALL
@@ -55,6 +55,10 @@ For most systems and configurations it is possible simply to:
|
||||
site. You will probably want to refer the sample.sudoers
|
||||
file and sudoers man page included with the sudo package.
|
||||
|
||||
8) If you want to use syslogd(8) to do the logging, you'll need
|
||||
to update your /etc/syslog.conf file. See the sample.syslog.conf
|
||||
file included in the distribution for an example.
|
||||
|
||||
Available configure options
|
||||
===========================
|
||||
|
||||
@@ -208,7 +212,8 @@ Special features/options:
|
||||
--with-loglen
|
||||
Number of characters per line for the file log. This is only used if
|
||||
you are to "file" or "both". This value is used to decide when to wrap
|
||||
lines for nicer log files. The default is 80.
|
||||
lines for nicer log files. The default is 80. Setting this to 0
|
||||
will disable the wrapping.
|
||||
|
||||
--with-ignore-dot
|
||||
If set, sudo will ignore '.' or '' (current dir) in $PATH.
|
||||
@@ -404,9 +409,6 @@ Special features/options:
|
||||
--enable-log-host
|
||||
Log the hostname in the log file.
|
||||
|
||||
--disable-log-wrap
|
||||
Do not wrap long lines in the log file.
|
||||
|
||||
--enable-noargs-shell
|
||||
If sudo is invoked with no arguments it acts as if the "-s" flag had
|
||||
been given. That is, it runs a shell as root (the shell is determined
|
||||
|
24
Makefile.in
24
Makefile.in
@@ -110,26 +110,26 @@ SHELL = /bin/sh
|
||||
|
||||
PROGS = @PROGS@
|
||||
|
||||
SRCS = alloc.c alloca.c check.c fileops.c find_path.c fnmatch.c getcwd.c \
|
||||
getspwuid.c goodpath.c interfaces.c lex.yy.c lsearch.c logging.c \
|
||||
parse.c parse.lex parse.yacc putenv.c snprintf.c strcasecmp.c \
|
||||
SRCS = alloc.c alloca.c check.c defaults.c fileops.c find_path.c fnmatch.c \
|
||||
getcwd.c getspwuid.c goodpath.c interfaces.c lex.yy.c lsearch.c \
|
||||
logging.c parse.c parse.lex parse.yacc putenv.c snprintf.c strcasecmp.c \
|
||||
strerror.c sudo.c sudo.tab.c sudo_setenv.c testsudoers.c tgetpass.c \
|
||||
utime.c version.c visudo.c $(AUTH_SRCS)
|
||||
utime.c visudo.c $(AUTH_SRCS)
|
||||
|
||||
AUTH_SRCS = auth/afs.c auth/aix_auth.c auth/dce.c auth/fwtk.c auth/kerb4.c \
|
||||
auth/kerb5.c auth/pam.c auth/passwd.c auth/rfc1938.c \
|
||||
auth/secureware.c auth/securid.c auth/sia.c auth/sudo_auth.c
|
||||
|
||||
HDRS = compat.h ins_2001.h ins_classic.h ins_csops.h ins_goons.h insults.h \
|
||||
interfaces.h logging.h parse.h sudo.h sudo.tab.h version.h \
|
||||
HDRS = compat.h defaults.h ins_2001.h ins_classic.h ins_csops.h ins_goons.h \
|
||||
insults.h interfaces.h logging.h parse.h sudo.h sudo.tab.h version.h \
|
||||
auth/sudo_auth.h emul/fnmatch.h emul/search.h emul/utime.h
|
||||
|
||||
AUTH_OBJS = sudo_auth.o @AUTH_OBJS@
|
||||
|
||||
PARSEOBJS = sudo.tab.o lex.yy.o alloc.o
|
||||
PARSEOBJS = sudo.tab.o lex.yy.o alloc.o defaults.o
|
||||
|
||||
SUDOBJS = check.o getspwuid.o goodpath.o fileops.o find_path.o interfaces.o \
|
||||
logging.o parse.o sudo.o sudo_setenv.o tgetpass.o version.o \
|
||||
logging.o parse.o sudo.o sudo_setenv.o tgetpass.o \
|
||||
$(AUTH_OBJS) $(PARSEOBJS)
|
||||
|
||||
VISUDOBJS = visudo.o fileops.o $(PARSEOBJS)
|
||||
@@ -148,8 +148,8 @@ DISTFILES = $(SRCS) $(HDRS) BUGS CHANGES FAQ HISTORY INSTALL INSTALL.configure \
|
||||
sudo.man sudo.pod sudoers sudoers.cat sudoers.man sudoers.pod \
|
||||
visudo.cat visudo.man visudo.pod auth/API
|
||||
|
||||
SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/logging.h \
|
||||
config.h pathnames.h
|
||||
SUDODEP = $(srcdir)/sudo.h $(srcdir)/compat.h $(srcdir)/defaults.h \
|
||||
$(srcdir)/logging.h config.h pathnames.h
|
||||
|
||||
AUTHDEP = $(SUDODEP) $(authdir)/sudo_auth.h
|
||||
|
||||
@@ -200,13 +200,13 @@ logging.o: logging.c $(SUDODEP)
|
||||
sudo_setenv.o: sudo_setenv.c $(SUDODEP)
|
||||
tgetpass.o: tgetpass.c $(SUDODEP)
|
||||
visudo.o: visudo.c $(SUDODEP) version.h
|
||||
sudo.o: sudo.c $(SUDODEP) interfaces.h
|
||||
sudo.o: sudo.c $(SUDODEP) interfaces.h version.h
|
||||
interfaces.o: interfaces.c $(SUDODEP) interfaces.h
|
||||
testsudoers.o: testsudoers.c $(SUDODEP) parse.h interfaces.h
|
||||
parse.o: parse.c $(SUDODEP) parse.h interfaces.h
|
||||
lex.yy.o: lex.yy.c $(SUDODEP) parse.h sudo.tab.h
|
||||
sudo.tab.o: sudo.tab.c $(SUDODEP) parse.h
|
||||
version.o: version.c $(SUDODEP) version.h auth/sudo_auth.h
|
||||
defaults.o: defaults.c $(SUDODEP) auth/sudo_auth.h
|
||||
fnmatch.o: fnmatch.c config.h compat.h emul/fnmatch.h
|
||||
getcwd.o: getcwd.c config.h compat.h
|
||||
lsearch.o: lsearch.c config.h compat.h emul/search.h
|
||||
|
4
TODO
4
TODO
@@ -68,3 +68,7 @@ TODO list (most will be addressed in sudo 2.0)
|
||||
user.
|
||||
|
||||
24) Use strtol() and strtoul(), not atoi()?
|
||||
|
||||
25) In parse.yacc get rid on unneeded '{ ; }'
|
||||
|
||||
26) Look into %e, %p, %k in parse.lex
|
||||
|
20
aclocal.m4
vendored
20
aclocal.m4
vendored
@@ -304,26 +304,6 @@ AC_MSG_RESULT($sudo_cv_uid_t_len)
|
||||
AC_DEFINE_UNQUOTED(MAX_UID_T_LEN, $sudo_cv_uid_t_len)
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl check for facilitynames and prioritynames in syslog.h
|
||||
dnl 4.4BSD has these but most others do not.
|
||||
dnl
|
||||
AC_DEFUN(SUDO_SYSLOG_NAMES,
|
||||
[AC_MSG_CHECKING(for facilitynames and prioritynames in syslog.h)
|
||||
AC_CACHE_VAL(sudo_cv_syslog_names,
|
||||
[
|
||||
AC_TRY_COMPILE([
|
||||
#define SYSLOG_NAMES
|
||||
#include <stdio.h>
|
||||
#include <syslog.h>
|
||||
], [ CODE *p=&prioritynames[0]; CODE *f=&facilitynames[0]; ],
|
||||
sudo_cv_syslog_names=yes, sudo_cv_syslog_names=no)])dnl
|
||||
AC_MSG_RESULT($sudo_cv_syslog_names)
|
||||
if test $sudo_cv_syslog_names = yes; then
|
||||
AC_DEFINE(HAVE_SYSLOG_NAMES)
|
||||
fi
|
||||
])
|
||||
|
||||
dnl
|
||||
dnl check for "long long"
|
||||
dnl XXX hard to cache since it includes 2 tests
|
||||
|
@@ -67,7 +67,7 @@ aixauth_verify(pw, prompt, auth)
|
||||
char *message, *pass;
|
||||
int reenter = 1;
|
||||
|
||||
pass = tgetpass(prompt, PASSWORD_TIMEOUT * 60, 1);
|
||||
pass = tgetpass(prompt, sudo_inttable[I_PW_TIMEOUT] * 60, 1);
|
||||
if (authenticate(pw->pw_name, pass, &reenter, &message) == 0)
|
||||
return(AUTH_SUCCESS);
|
||||
else
|
||||
|
@@ -117,9 +117,9 @@ fwtk_verify(pw, prompt, auth)
|
||||
/* Get the password/response from the user. */
|
||||
if (strncmp(resp, "challenge ", 10) == 0) {
|
||||
(void) snprintf(buf, sizeof(buf), "%s\nResponse: ", &resp[10]);
|
||||
pass = tgetpass(buf, PASSWORD_TIMEOUT * 60, 0);
|
||||
pass = tgetpass(buf, sudo_inttable[I_PW_TIMEOUT] * 60, 0);
|
||||
} else if (strncmp(resp, "password", 8) == 0) {
|
||||
pass = tgetpass(prompt, PASSWORD_TIMEOUT * 60, 1);
|
||||
pass = tgetpass(prompt, sudo_inttable[I_PW_TIMEOUT] * 60, 1);
|
||||
} else {
|
||||
(void) fprintf(stderr, "%s: %s\n", Argv[0], resp);
|
||||
return(AUTH_FATAL);
|
||||
|
@@ -103,7 +103,7 @@ kerb5_init(pw, promptp, auth)
|
||||
realm = lrealm;
|
||||
|
||||
/* Only rewrite prompt if user didn't specify their own. */
|
||||
if (!strcmp(prompt, PASSPROMPT))
|
||||
if (user_prompt == NULL)
|
||||
easprintf(promptp, "Password for %s@%s: ", pw->pw_name, realm);
|
||||
return(AUTH_SUCCESS);
|
||||
}
|
||||
|
@@ -143,7 +143,7 @@ sudo_conv(num_msg, msg, response, appdata_ptr)
|
||||
if (strcmp(p, "Password: ") && strcmp(p, "Password:"))
|
||||
p = (char *) pm->msg;
|
||||
pr->resp = estrdup((char *) tgetpass(p,
|
||||
PASSWORD_TIMEOUT * 60, !echo));
|
||||
sudo_inttable[I_PW_TIMEOUT] * 60, !echo));
|
||||
if (*pr->resp == '\0')
|
||||
nil_pw = 1; /* empty password */
|
||||
break;
|
||||
|
@@ -93,6 +93,9 @@ rfc1938_setup(pw, promptp, auth)
|
||||
/* Ignore trailing colon (we will add our own) */
|
||||
if (orig_prompt[op_len - 1] == ':')
|
||||
op_len--;
|
||||
else if (op_len >= 2 && orig_prompt[op_len - 1] == ' '
|
||||
&& orig_prompt[op_len - 2] == ':')
|
||||
op_len -= 2;
|
||||
}
|
||||
|
||||
#ifdef HAVE_SKEY
|
||||
@@ -123,11 +126,11 @@ rfc1938_setup(pw, promptp, auth)
|
||||
new_prompt = (char *) erealloc(new_prompt, np_size);
|
||||
}
|
||||
|
||||
#ifdef LONG_OTP_PROMPT
|
||||
(void) sprintf(new_prompt, "%s\n%s", challenge, orig_prompt);
|
||||
#else
|
||||
(void) sprintf(new_prompt, "%.*s [ %s ]:", op_len, orig_prompt, challenge);
|
||||
#endif /* LONG_OTP_PROMPT */
|
||||
if (sudo_flag_set(FL_LONG_OTP_PROMPT))
|
||||
(void) sprintf(new_prompt, "%s\n%s", challenge, orig_prompt);
|
||||
else
|
||||
(void) sprintf(new_prompt, "%.*s [ %s ]:", op_len, orig_prompt,
|
||||
challenge);
|
||||
|
||||
*promptp = new_prompt;
|
||||
return(AUTH_SUCCESS);
|
||||
|
@@ -80,8 +80,8 @@ sudo_collect(timeout, rendition, title, nprompts, prompts)
|
||||
switch (rendition) {
|
||||
case SIAFORM:
|
||||
case SIAONELINER:
|
||||
if (timeout <= 0 || timeout > PASSWORD_TIMEOUT * 60)
|
||||
timeout = PASSWORD_TIMEOUT * 60;
|
||||
if (timeout <= 0 || timeout > sudo_inttable[I_PW_TIMEOUT] * 60)
|
||||
timeout = sudo_inttable[I_PW_TIMEOUT] * 60;
|
||||
/*
|
||||
* Substitute custom prompt if a) the sudo prompt is not "Password:"
|
||||
* and b) the SIA prompt is "Password:" (so we know it is safe).
|
||||
|
@@ -95,9 +95,10 @@ sudo_auth auth_switch[] = {
|
||||
int nil_pw; /* I hate resorting to globals like this... */
|
||||
|
||||
void
|
||||
verify_user()
|
||||
verify_user(prompt)
|
||||
char *prompt;
|
||||
{
|
||||
short counter = TRIES_FOR_PASSWORD + 1;
|
||||
short counter = sudo_inttable[I_PW_TRIES] + 1;
|
||||
short success = AUTH_FAILURE;
|
||||
short status;
|
||||
char *p;
|
||||
@@ -120,7 +121,7 @@ verify_user()
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_USER, 0);
|
||||
|
||||
status = (auth->init)(sudo_user.pw, &user_prompt, auth);
|
||||
status = (auth->init)(sudo_user.pw, &prompt, auth);
|
||||
if (status == AUTH_FAILURE)
|
||||
auth->flags &= ~FLAG_CONFIGURED;
|
||||
else if (status == AUTH_FATAL) /* XXX log */
|
||||
@@ -138,7 +139,7 @@ verify_user()
|
||||
if (NEEDS_USER(auth))
|
||||
set_perms(PERM_USER, 0);
|
||||
|
||||
status = (auth->setup)(sudo_user.pw, &user_prompt, auth);
|
||||
status = (auth->setup)(sudo_user.pw, &prompt, auth);
|
||||
if (status == AUTH_FAILURE)
|
||||
auth->flags &= ~FLAG_CONFIGURED;
|
||||
else if (status == AUTH_FATAL) /* XXX log */
|
||||
@@ -152,9 +153,9 @@ verify_user()
|
||||
/* Get the password unless the auth function will do it for us */
|
||||
nil_pw = 0;
|
||||
#ifdef AUTH_STANDALONE
|
||||
p = user_prompt;
|
||||
p = prompt;
|
||||
#else
|
||||
p = (char *) tgetpass(user_prompt, PASSWORD_TIMEOUT * 60, 1);
|
||||
p = (char *) tgetpass(prompt, sudo_inttable[I_PW_TIMEOUT] * 60, 1);
|
||||
if (!p || *p == '\0')
|
||||
nil_pw = 1;
|
||||
#endif /* AUTH_STANDALONE */
|
||||
@@ -181,7 +182,7 @@ verify_user()
|
||||
|
||||
/* Exit loop on nil password, but give it a chance to match first. */
|
||||
if (nil_pw) {
|
||||
if (counter == TRIES_FOR_PASSWORD)
|
||||
if (counter == sudo_inttable[I_PW_TRIES])
|
||||
exit(1);
|
||||
else
|
||||
break;
|
||||
@@ -211,8 +212,8 @@ cleanup:
|
||||
return;
|
||||
case AUTH_FAILURE:
|
||||
log_error(NO_MAIL, "%d incorrect password attempt%s",
|
||||
TRIES_FOR_PASSWORD - counter,
|
||||
(TRIES_FOR_PASSWORD - counter == 1) ? "" : "s");
|
||||
sudo_inttable[I_PW_TRIES] - counter,
|
||||
(sudo_inttable[I_PW_TRIES] - counter == 1) ? "" : "s");
|
||||
case AUTH_FATAL:
|
||||
exit(1);
|
||||
}
|
||||
@@ -226,6 +227,17 @@ pass_warn(fp)
|
||||
#ifdef USE_INSULTS
|
||||
(void) fprintf(fp, "%s\n", INSULT);
|
||||
#else
|
||||
(void) fprintf(fp, "%s\n", INCORRECT_PASSWORD);
|
||||
(void) fprintf(fp, "%s\n", sudo_strtable[I_BADPASS_MSG]);
|
||||
#endif /* USE_INSULTS */
|
||||
}
|
||||
|
||||
void
|
||||
dump_auth_methods()
|
||||
{
|
||||
sudo_auth *auth;
|
||||
|
||||
(void) fputs("Authentication methods:", stdout);
|
||||
for (auth = auth_switch; auth->name; auth++)
|
||||
(void) printf(" '%s'", auth->name);
|
||||
(void) putchar('\n');
|
||||
}
|
||||
|
91
check.c
91
check.c
@@ -87,6 +87,7 @@ check_user()
|
||||
{
|
||||
char *timestampdir = NULL;
|
||||
char *timestampfile = NULL;
|
||||
char *prompt;
|
||||
int status;
|
||||
|
||||
if (user_uid == 0 || user_is_exempt())
|
||||
@@ -99,9 +100,9 @@ check_user()
|
||||
lecture(); /* first time through they get a lecture */
|
||||
|
||||
/* Expand any escapes in the prompt. */
|
||||
user_prompt = expand_prompt(user_prompt, user_name, user_shost);
|
||||
prompt = expand_prompt(user_prompt ? user_prompt : sudo_strtable[I_PASSPROMPT], user_name, user_shost);
|
||||
|
||||
verify_user();
|
||||
verify_user(prompt);
|
||||
}
|
||||
if (status != TS_ERROR)
|
||||
update_timestamp(timestampdir, timestampfile);
|
||||
@@ -112,20 +113,21 @@ check_user()
|
||||
|
||||
/*
|
||||
* Standard sudo lecture.
|
||||
* TODO: allow the user to specify a file name instead at compile time.
|
||||
* TODO: allow the user to specify a file name instead.
|
||||
*/
|
||||
static void
|
||||
lecture()
|
||||
{
|
||||
#ifndef NO_LECTURE
|
||||
(void) fputs("\n\
|
||||
|
||||
if (sudo_flag_set(FL_LECTURE)) {
|
||||
(void) fputs("\n\
|
||||
We trust you have received the usual lecture from the local System\n\
|
||||
Administrator. It usually boils down to these two things:\n\
|
||||
\n\
|
||||
#1) Respect the privacy of others.\n\
|
||||
#2) Think before you type.\n\n",
|
||||
stderr);
|
||||
#endif /* NO_LECTURE */
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -188,7 +190,7 @@ expand_prompt(old_prompt, user, host)
|
||||
|
||||
if (subst) {
|
||||
new_prompt = (char *) emalloc(len + 1);
|
||||
for (p = user_prompt, np = new_prompt; *p; p++) {
|
||||
for (p = old_prompt, np = new_prompt; *p; p++) {
|
||||
if (lastchar == '%' && (*p == 'h' || *p == 'u' || *p == '%')) {
|
||||
/* substiture user/host name */
|
||||
if (*p == 'h') {
|
||||
@@ -210,7 +212,7 @@ expand_prompt(old_prompt, user, host)
|
||||
}
|
||||
*np = '\0';
|
||||
} else
|
||||
new_prompt = user_prompt;
|
||||
new_prompt = old_prompt;
|
||||
|
||||
return(new_prompt);
|
||||
}
|
||||
@@ -221,11 +223,13 @@ expand_prompt(old_prompt, user, host)
|
||||
int
|
||||
user_is_exempt()
|
||||
{
|
||||
#ifdef EXEMPTGROUP
|
||||
struct group *grp;
|
||||
char **gr_mem;
|
||||
|
||||
if (!(grp = getgrnam(EXEMPTGROUP)))
|
||||
if (!sudo_strtable[I_EXEMPT_GRP])
|
||||
return(FALSE);
|
||||
|
||||
if (!(grp = getgrnam(sudo_strtable[I_EXEMPT_GRP])))
|
||||
return(FALSE);
|
||||
|
||||
if (getgid() == grp->gr_gid)
|
||||
@@ -235,7 +239,6 @@ user_is_exempt()
|
||||
if (strcmp(user_name, *gr_mem) == 0)
|
||||
return(TRUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(FALSE);
|
||||
}
|
||||
@@ -248,26 +251,26 @@ build_timestamp(timestampdir, timestampfile)
|
||||
char **timestampdir;
|
||||
char **timestampfile;
|
||||
{
|
||||
#ifdef USE_TTY_TICKETS
|
||||
char *p;
|
||||
char *dirparent = sudo_strtable[I_TIMESTAMPDIR];
|
||||
|
||||
if ((p = strrchr(user_tty, '/')))
|
||||
p++;
|
||||
else
|
||||
p = user_tty;
|
||||
if (sizeof(_PATH_SUDO_TIMEDIR) + strlen(user_name) + strlen(p) + 2 >
|
||||
MAXPATHLEN)
|
||||
log_error(0, "timestamp path too long: %s/%s/%s", _PATH_SUDO_TIMEDIR,
|
||||
user_name, p);
|
||||
easprintf(timestampdir, "%s/%s", _PATH_SUDO_TIMEDIR, user_name);
|
||||
easprintf(timestampfile, "%s/%s/%s", _PATH_SUDO_TIMEDIR, user_name, p);
|
||||
#else
|
||||
if (sizeof(_PATH_SUDO_TIMEDIR) + strlen(user_name) + 1 > MAXPATHLEN)
|
||||
log_error(0, "timestamp path too long: %s/%s", _PATH_SUDO_TIMEDIR,
|
||||
user_name);
|
||||
easprintf(timestampdir, "%s/%s", _PATH_SUDO_TIMEDIR, user_name);
|
||||
*timestampfile = NULL;
|
||||
#endif /* USE_TTY_TICKETS */
|
||||
if (sudo_flag_set(FL_TTY_TICKETS)) {
|
||||
char *p;
|
||||
|
||||
if ((p = strrchr(user_tty, '/')))
|
||||
p++;
|
||||
else
|
||||
p = user_tty;
|
||||
if (strlen(dirparent) + strlen(user_name) + strlen(p) + 3 > MAXPATHLEN)
|
||||
log_error(0, "timestamp path too long: %s/%s/%s", dirparent,
|
||||
user_name, p);
|
||||
easprintf(timestampdir, "%s/%s", dirparent, user_name);
|
||||
easprintf(timestampfile, "%s/%s/%s", dirparent, user_name, p);
|
||||
} else {
|
||||
if (strlen(dirparent) + strlen(user_name) + 2 > MAXPATHLEN)
|
||||
log_error(0, "timestamp path too long: %s/%s", dirparent, user_name);
|
||||
easprintf(timestampdir, "%s/%s", dirparent, user_name);
|
||||
*timestampfile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -282,39 +285,40 @@ timestamp_status(timestampdir, timestampfile, user, make_dirs)
|
||||
{
|
||||
struct stat sb;
|
||||
time_t now;
|
||||
char *dirparent = sudo_strtable[I_TIMESTAMPDIR];
|
||||
int status = TS_ERROR; /* assume the worst */
|
||||
|
||||
/*
|
||||
* Sanity check _PATH_SUDO_TIMEDIR and make it if it doesn't already exist.
|
||||
* Sanity check dirparent and make it if it doesn't already exist.
|
||||
* We start out assuming the worst (that the dir is not sane) and
|
||||
* if it is ok upgrade the status to ``no timestamp file''.
|
||||
* Note that we don't check the parent(s) of _PATH_SUDO_TIMEDIR for
|
||||
* Note that we don't check the parent(s) of dirparent for
|
||||
* sanity since the sudo dir is often just located in /tmp.
|
||||
*/
|
||||
if (lstat(_PATH_SUDO_TIMEDIR, &sb) == 0) {
|
||||
if (lstat(dirparent, &sb) == 0) {
|
||||
if (!S_ISDIR(sb.st_mode))
|
||||
log_error(NO_EXIT, "%s exists but is not a directory (0%o)",
|
||||
_PATH_SUDO_TIMEDIR, sb.st_mode);
|
||||
dirparent, sb.st_mode);
|
||||
else if (sb.st_uid != 0)
|
||||
log_error(NO_EXIT, "%s owned by uid %ld, should be owned by root",
|
||||
_PATH_SUDO_TIMEDIR, (long) sb.st_uid);
|
||||
dirparent, (long) sb.st_uid);
|
||||
else if ((sb.st_mode & 0000022))
|
||||
log_error(NO_EXIT,
|
||||
"%s writable by non-owner (0%o), should be mode 0700",
|
||||
_PATH_SUDO_TIMEDIR, sb.st_mode);
|
||||
dirparent, sb.st_mode);
|
||||
else {
|
||||
if ((sb.st_mode & 0000777) != 0700)
|
||||
(void) chmod(_PATH_SUDO_TIMEDIR, 0700);
|
||||
(void) chmod(dirparent, 0700);
|
||||
status = TS_MISSING;
|
||||
}
|
||||
} else if (errno != ENOENT) {
|
||||
log_error(NO_EXIT|USE_ERRNO, "can't stat %s", _PATH_SUDO_TIMEDIR);
|
||||
log_error(NO_EXIT|USE_ERRNO, "can't stat %s", dirparent);
|
||||
} else {
|
||||
/* No _PATH_SUDO_TIMEDIR, try to make one. */
|
||||
/* No dirparent, try to make one. */
|
||||
if (make_dirs) {
|
||||
if (mkdir(_PATH_SUDO_TIMEDIR, S_IRWXU))
|
||||
if (mkdir(dirparent, S_IRWXU))
|
||||
log_error(NO_EXIT|USE_ERRNO, "can't mkdir %s",
|
||||
_PATH_SUDO_TIMEDIR);
|
||||
dirparent);
|
||||
else
|
||||
status = TS_MISSING;
|
||||
}
|
||||
@@ -408,12 +412,13 @@ timestamp_status(timestampdir, timestampfile, user, make_dirs)
|
||||
*/
|
||||
if (status == TS_OLD) {
|
||||
now = time(NULL);
|
||||
if (TIMEOUT && now - sb.st_mtime < 60 * TIMEOUT) {
|
||||
if (sudo_inttable[I_TS_TIMEOUT] &&
|
||||
now - sb.st_mtime < 60 * sudo_inttable[I_TS_TIMEOUT]) {
|
||||
/*
|
||||
* Check for bogus time on the stampfile. The clock may
|
||||
* have been set back or someone could be trying to spoof us.
|
||||
*/
|
||||
if (sb.st_mtime > now + 60 * TIMEOUT * 2) {
|
||||
if (sb.st_mtime > now + 60 * sudo_inttable[I_TS_TIMEOUT] * 2) {
|
||||
log_error(NO_EXIT,
|
||||
"timestamp too far in the future: %20.20s",
|
||||
4 + ctime(&sb.st_mtime));
|
||||
|
@@ -397,9 +397,6 @@
|
||||
/* Define if you want the hostname to be entered into the log file */
|
||||
#undef HOST_IN_LOG
|
||||
|
||||
/* Define if you want the log file line to be wrapped */
|
||||
#undef WRAP_LOG
|
||||
|
||||
/* Define to be the number of minutes before sudo asks for passwd again. */
|
||||
#undef TIMEOUT
|
||||
|
||||
@@ -454,9 +451,6 @@
|
||||
/* Define to be the max chars per log line (for line wrapping). */
|
||||
#undef MAXLOGFILELEN
|
||||
|
||||
/* Define if your syslog.h has the prioritynames and facilitynames tables. */
|
||||
#undef HAVE_SYSLOG_NAMES
|
||||
|
||||
/* Define if you want to ignore '.' and '' in $PATH */
|
||||
#undef IGNORE_DOT_PATH
|
||||
|
||||
|
23
configure.in
23
configure.in
@@ -932,24 +932,6 @@ AC_ARG_ENABLE(log-host,
|
||||
esac
|
||||
], AC_MSG_RESULT(no))
|
||||
|
||||
AC_MSG_CHECKING(whether to wrap long lines in the log file)
|
||||
AC_ARG_ENABLE(log-wrap,
|
||||
[ --disable-log-wrap Do not wrap long lines in the log file],
|
||||
[ case "$enableval" in
|
||||
yes) AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(WRAP_LOG)
|
||||
;;
|
||||
no) AC_MSG_RESULT(no)
|
||||
;;
|
||||
*) AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(WRAP_LOG)
|
||||
echo "Ignoring unknown argument to --enable-log-wrap: $enableval"
|
||||
;;
|
||||
esac
|
||||
], AC_MSG_RESULT(yes)
|
||||
AC_DEFINE(WRAP_LOG)
|
||||
)
|
||||
|
||||
AC_MSG_CHECKING(whether to invoke a shell if sudo is given no arguments)
|
||||
AC_ARG_ENABLE(noargs-shell,
|
||||
[ --enable-noargs-shell If sudo is given no arguments run a shell],
|
||||
@@ -1470,11 +1452,6 @@ if test "$with_DCE" = "yes" -o "$ac_cv_prog_YACC" = "bison -y"; then
|
||||
AC_FUNC_ALLOCA
|
||||
fi
|
||||
|
||||
dnl
|
||||
dnl Check to see if the facility and priority names live in syslog.h
|
||||
dnl
|
||||
SUDO_SYSLOG_NAMES
|
||||
|
||||
dnl
|
||||
dnl Kerberos 5
|
||||
dnl
|
||||
|
613
defaults.c
Normal file
613
defaults.c
Normal file
@@ -0,0 +1,613 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "Sudo" nor
|
||||
* may "Sudo" appear in their names without specific prior written
|
||||
* permission from the author.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef STDC_HEADERS
|
||||
#include <stdlib.h>
|
||||
#endif /* STDC_HEADERS */
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#include "sudo.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$Sudo$";
|
||||
#endif /* lint */
|
||||
|
||||
/*
|
||||
* For converting between syslog numbers and strings.
|
||||
*/
|
||||
struct strmap {
|
||||
char *name;
|
||||
int num;
|
||||
};
|
||||
|
||||
static struct strmap facilities[] = {
|
||||
#ifdef LOG_AUTHPRIV
|
||||
{ "authpriv", LOG_AUTHPRIV },
|
||||
#endif
|
||||
{ "auth", LOG_AUTH },
|
||||
{ "daemon", LOG_DAEMON },
|
||||
{ "user", LOG_USER },
|
||||
{ "local0", LOG_LOCAL0 },
|
||||
{ "local1", LOG_LOCAL1 },
|
||||
{ "local2", LOG_LOCAL2 },
|
||||
{ "local3", LOG_LOCAL3 },
|
||||
{ "local4", LOG_LOCAL4 },
|
||||
{ "local5", LOG_LOCAL5 },
|
||||
{ "local6", LOG_LOCAL6 },
|
||||
{ "local7", LOG_LOCAL7 },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
static struct strmap priorities[] = {
|
||||
{ "alert", LOG_ALERT },
|
||||
{ "crit", LOG_CRIT },
|
||||
{ "debug", LOG_DEBUG },
|
||||
{ "emerg", LOG_EMERG },
|
||||
{ "err", LOG_ERR },
|
||||
{ "info", LOG_INFO },
|
||||
{ "notice", LOG_NOTICE },
|
||||
{ "warning", LOG_WARNING },
|
||||
{ NULL, -1 }
|
||||
};
|
||||
|
||||
/*
|
||||
* Local prototypes.
|
||||
*/
|
||||
static int store_int __P((char *, int, int));
|
||||
static int store_str __P((char *, int, int));
|
||||
static int store_syslogfac __P((char *, int, int));
|
||||
static int store_syslogpri __P((char *, int, int));
|
||||
static int store_umask __P((char *, int, int));
|
||||
static char *num_to_name __P((int, struct strmap *));
|
||||
|
||||
/*
|
||||
* Structure describing compile-time and run-time options.
|
||||
* Index for T_INT starts at one since index 0 is for flags.
|
||||
* XXX - syslog things should be strings (and !facility should turn off)
|
||||
* XXX - some of these names are pretty lame.
|
||||
*/
|
||||
struct sudo_defs_types {
|
||||
char *name;
|
||||
unsigned int type;
|
||||
unsigned int index;
|
||||
int (*store) __P((char *, int, int));
|
||||
char *desc;
|
||||
} sudo_defs_table[] = {
|
||||
{
|
||||
"long_otp_prompt", T_FLAG, FL_LONG_OTP_PROMPT, NULL,
|
||||
"Put OTP prompt on its own line"
|
||||
}, {
|
||||
"ignore_dot", T_FLAG, FL_IGNORE_DOT, NULL,
|
||||
"Ignore '.' in $PATH"
|
||||
}, {
|
||||
"mail_if_no_user", T_FLAG, FL_MAIL_IF_NOUSER, NULL,
|
||||
"Send mail if the user is not in sudoers"
|
||||
}, {
|
||||
"mail_if_no_host", T_FLAG, FL_MAIL_IF_NOHOST, NULL,
|
||||
"Send mail if the user is not in sudoers for this host"
|
||||
}, {
|
||||
"mail_if_no_perms", T_FLAG, FL_MAIL_IF_NOPERMS, NULL,
|
||||
"Send mail if the user is not allowed to run a command"
|
||||
}, {
|
||||
"tty_tickets", T_FLAG, FL_TTY_TICKETS, NULL,
|
||||
"Use a separate timestamp for each user/tty combo"
|
||||
}, {
|
||||
"lecture", T_FLAG, FL_LECTURE, NULL,
|
||||
"Lecture user the first time they run sudo"
|
||||
}, {
|
||||
"authenticate", T_FLAG, FL_AUTHENTICATE, NULL,
|
||||
"Require users to authenticate by default"
|
||||
}, {
|
||||
"root_sudo", T_FLAG, FL_ROOT_SUDO, NULL,
|
||||
"Root may run sudo"
|
||||
}, {
|
||||
"log_host", T_FLAG, FL_LOG_HOST, NULL,
|
||||
"Log the hostname in the (non-syslog) log file"
|
||||
}, {
|
||||
"shell_noargs", T_FLAG, FL_SHELL_NOARGS, NULL,
|
||||
"If sudo is invoked with no arguments, start a shell"
|
||||
}, {
|
||||
"set_home", T_FLAG, FL_SET_HOME, NULL,
|
||||
"Set $HOME to the target user when starting a shell with -s"
|
||||
}, {
|
||||
"path_info", T_FLAG, FL_PATH_INFO, NULL,
|
||||
"Allow some information gathering to give useful error messages"
|
||||
}, {
|
||||
"fqdn", T_FLAG, FL_FQDN, NULL,
|
||||
"Require fully-qualified hsotnames in the sudoers file"
|
||||
}, {
|
||||
"insults", T_FLAG, FL_INSULTS, NULL,
|
||||
"Insult the user when they enter an incorrect password"
|
||||
}, {
|
||||
"syslog", T_INT|T_BOOL, I_LOGFAC, store_syslogfac,
|
||||
"Syslog facility: %s"
|
||||
}, {
|
||||
"syslog_goodpri", T_INT, I_GOODPRI, store_syslogpri,
|
||||
"Syslog priority to use when user authenticates successfully: %s"
|
||||
}, {
|
||||
"syslog_badpri", T_INT, I_BADPRI, store_syslogpri,
|
||||
"Syslog priority to use when user authenticates unsuccessfully: %s"
|
||||
}, {
|
||||
"loglinelen", T_INT, I_LOGLEN, store_int,
|
||||
"Number of length at which to wrap log file lines (0 for no wrap): %d"
|
||||
}, {
|
||||
"timestamp_timeout", T_INT, I_TS_TIMEOUT, store_int,
|
||||
"Authentication timestamp timeout: %d minutes"
|
||||
}, {
|
||||
"passwd_timeout", T_INT, I_PW_TIMEOUT, store_int,
|
||||
"Password prompt timeout: %d minutes"
|
||||
}, {
|
||||
"passwd_tries", T_INT, I_PW_TRIES, store_int,
|
||||
"Number of tries to enter a password: %d"
|
||||
}, {
|
||||
"umask", T_INT|T_BOOL, I_UMASK, store_umask,
|
||||
"Umask to use or 0777 to use user's: 0%o"
|
||||
}, {
|
||||
"logfile", T_STR, I_LOGFILE, store_str,
|
||||
"Path to log file: %s"
|
||||
}, {
|
||||
"mailerpath", T_STR, I_MAILERPATH, store_str,
|
||||
"Path to mail program: %s"
|
||||
}, {
|
||||
"mailerflags", T_STR, I_MAILERARGS, store_str,
|
||||
"Flags for mail program: %s"
|
||||
}, {
|
||||
"alertmail", T_STR, I_ALERTMAIL, store_str,
|
||||
"Address to send mail to: %s"
|
||||
}, {
|
||||
"mailsub", T_STR, I_MAILSUB, store_str,
|
||||
"Subject line for mail messages: %s"
|
||||
}, {
|
||||
"badpass_message", T_STR, I_BADPASS_MSG, store_str,
|
||||
"Incorrect password message: %s"
|
||||
}, {
|
||||
"timestampdir", T_STR, I_TIMESTAMPDIR, store_str,
|
||||
"Path to authentication timestamp dir: %s"
|
||||
}, {
|
||||
"exempt_group", T_STR, I_EXEMPT_GRP, store_str,
|
||||
"Users in this group are exempt from password and PATH requirements: %s"
|
||||
}, {
|
||||
"passprompt", T_STR, I_PASSPROMPT, store_str,
|
||||
"Default password prompt: %s"
|
||||
}, {
|
||||
"runas_default", T_STR, I_RUNAS_DEF, store_str,
|
||||
"Default user to run commands as: %s"
|
||||
}, {
|
||||
"secure_path", T_STR, I_SECURE_PATH, store_str,
|
||||
"Override user's $PATH with: %s"
|
||||
}, {
|
||||
NULL, 0, 0, NULL, NULL
|
||||
}
|
||||
};
|
||||
|
||||
unsigned int sudo_inttable[SUDO_INTTABLE_LAST];
|
||||
char *sudo_strtable[SUDO_STRTABLE_LAST];
|
||||
|
||||
/*
|
||||
* Print version and configure info.
|
||||
*/
|
||||
void
|
||||
dump_defaults()
|
||||
{
|
||||
struct sudo_defs_types *cur;
|
||||
|
||||
for (cur = sudo_defs_table; cur->name; cur++) {
|
||||
switch (cur->type & T_MASK) {
|
||||
case T_FLAG:
|
||||
if ((sudo_inttable[I_FLAGS]) & (cur->index))
|
||||
puts(cur->desc);
|
||||
break;
|
||||
case T_STR:
|
||||
if (sudo_strtable[cur->index]) {
|
||||
(void) printf(cur->desc, sudo_strtable[cur->index]);
|
||||
putchar('\n');
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
if (cur->index == I_LOGFAC)
|
||||
(void) printf(cur->desc,
|
||||
num_to_name(sudo_inttable[cur->index], facilities));
|
||||
else if (cur->index == I_GOODPRI || cur->index == I_BADPRI)
|
||||
(void) printf(cur->desc,
|
||||
num_to_name(sudo_inttable[cur->index], priorities));
|
||||
else
|
||||
(void) printf(cur->desc, sudo_inttable[cur->index]);
|
||||
putchar('\n');
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENV_EDITOR
|
||||
(void) printf("Default editor for visudo: %s\n", EDITOR);
|
||||
#else
|
||||
(void) printf("Editor for visudo: %s\n", EDITOR);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
* List each option along with its description.
|
||||
*/
|
||||
void
|
||||
list_options()
|
||||
{
|
||||
struct sudo_defs_types *cur;
|
||||
char *p;
|
||||
|
||||
(void) puts("Available options in a sudoers ``Defaults'' line:\n");
|
||||
for (cur = sudo_defs_table; cur->name; cur++) {
|
||||
switch (cur->type & T_MASK) {
|
||||
case T_FLAG:
|
||||
(void) printf("%s: %s\n", cur->name, cur->desc);
|
||||
break;
|
||||
case T_STR:
|
||||
case T_INT:
|
||||
p = strrchr(cur->desc, ':');
|
||||
if (p)
|
||||
(void) printf("%s: %.*s\n", cur->name, p - cur->desc,
|
||||
cur->desc);
|
||||
else
|
||||
(void) printf("%s: %s\n", cur->name, cur->desc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert a syslog number to a name.
|
||||
*/
|
||||
static char *
|
||||
num_to_name(num, table)
|
||||
int num;
|
||||
struct strmap *table;
|
||||
{
|
||||
struct strmap *t;
|
||||
|
||||
for (t = table; t->name; t++)
|
||||
if (t->num == num)
|
||||
return(t->name);
|
||||
|
||||
return("disabled");
|
||||
}
|
||||
|
||||
/*
|
||||
* Sets/clears an entry in the defaults structure
|
||||
* If a variable that takes a value is used in a boolean
|
||||
* context with op == 0, disable that variable.
|
||||
* Eg. you may want to turn off logging to a file for some hosts.
|
||||
* This is only meaningful for variables that are *optional*.
|
||||
*/
|
||||
int
|
||||
set_default(var, val, op)
|
||||
char *var;
|
||||
char *val;
|
||||
int op; /* TRUE or FALSE */
|
||||
{
|
||||
struct sudo_defs_types *cur;
|
||||
extern int sudolineno;
|
||||
|
||||
for (cur = sudo_defs_table; cur->name; cur++) {
|
||||
if (strcmp(var, cur->name) == 0)
|
||||
break;
|
||||
}
|
||||
if (!cur->name) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: unknown defaults entry `%s' referenced near line %d\n", Argv[0],
|
||||
var, sudolineno);
|
||||
return(FALSE);
|
||||
}
|
||||
|
||||
switch (cur->type & T_MASK) {
|
||||
case T_STR:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!(cur->type & T_BOOL) || op != FALSE) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: no value specified for `%s' on line %d\n", Argv[0],
|
||||
var, sudolineno);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
if (!cur->store(val, cur->index, op)) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: value '%s' is invalid for option '%s'\n", Argv[0],
|
||||
val, var);
|
||||
return(FALSE);
|
||||
}
|
||||
break;
|
||||
case T_INT:
|
||||
if (!val) {
|
||||
/* Check for bogus boolean usage or lack of a value. */
|
||||
if (!(cur->type & T_BOOL) || op != FALSE) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: no value specified for `%s' on line %d\n", Argv[0],
|
||||
var, sudolineno);
|
||||
return(FALSE);
|
||||
}
|
||||
}
|
||||
if (!cur->store(val, cur->index, op)) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: value '%s' is invalid for option '%s'\n", Argv[0],
|
||||
val, var);
|
||||
return(FALSE);
|
||||
}
|
||||
break;
|
||||
case T_FLAG:
|
||||
if (val) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: option `%s' does not take a value on line %d\n",
|
||||
Argv[0], var, sudolineno);
|
||||
return(FALSE);
|
||||
}
|
||||
if (op == TRUE)
|
||||
sudo_inttable[0] |= cur->index;
|
||||
else
|
||||
sudo_inttable[0] &= ~(cur->index);
|
||||
break;
|
||||
}
|
||||
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set default options to compiled-in values.
|
||||
* Any of these may be overridden at runtime by a "Defaults" file.
|
||||
*/
|
||||
void
|
||||
init_defaults()
|
||||
{
|
||||
static int firsttime = 1;
|
||||
int i;
|
||||
|
||||
/* Free any strings that were set. */
|
||||
if (!firsttime) {
|
||||
for (i = 0; i < SUDO_STRTABLE_LAST; i++)
|
||||
if (sudo_strtable[i])
|
||||
free(sudo_strtable[i]);
|
||||
}
|
||||
|
||||
memset(sudo_strtable, 0, sizeof(sudo_strtable));
|
||||
memset(sudo_inttable, 0, sizeof(sudo_inttable));
|
||||
|
||||
/* First initialize the flags. */
|
||||
#ifdef LONG_OTP_PROMPT
|
||||
sudo_inttable[I_FLAGS] |= FL_LONG_OTP_PROMPT;
|
||||
#endif
|
||||
#ifdef IGNORE_DOT_PATH
|
||||
sudo_inttable[I_FLAGS] |= FL_IGNORE_DOT;
|
||||
#endif
|
||||
#ifdef ALWAYS_SEND_MAIL
|
||||
sudo_inttable[I_FLAGS] |= FL_MAIL_ALWAYS;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NO_USER
|
||||
sudo_inttable[I_FLAGS] |= FL_MAIL_IF_NOUSER;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NO_HOST
|
||||
sudo_inttable[I_FLAGS] |= FL_MAIL_IF_NOHOST;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NOT_OK
|
||||
sudo_inttable[I_FLAGS] |= FL_MAIL_IF_NOPERMS;
|
||||
#endif
|
||||
#ifdef USE_TTY_TICKETS
|
||||
sudo_inttable[I_FLAGS] |= FL_TTY_TICKETS;
|
||||
#endif
|
||||
#ifndef NO_LECTURE
|
||||
sudo_inttable[I_FLAGS] |= FL_LECTURE;
|
||||
#endif
|
||||
#ifndef NO_AUTHENTICATION
|
||||
sudo_inttable[I_FLAGS] |= FL_AUTHENTICATE;
|
||||
#endif
|
||||
#ifndef NO_ROOT_SUDO
|
||||
sudo_inttable[I_FLAGS] |= FL_ROOT_SUDO;
|
||||
#endif
|
||||
#ifdef HOST_IN_LOG
|
||||
sudo_inttable[I_FLAGS] |= FL_LOG_HOST;
|
||||
#endif
|
||||
#ifdef SHELL_IF_NO_ARGS
|
||||
sudo_inttable[I_FLAGS] |= FL_SHELL_NOARGS;
|
||||
#endif
|
||||
#ifdef SHELL_SETS_HOME
|
||||
sudo_inttable[I_FLAGS] |= FL_SET_HOME;
|
||||
#endif
|
||||
#ifndef DONT_LEAK_PATH_INFO
|
||||
sudo_inttable[I_FLAGS] |= FL_PATH_INFO;
|
||||
#endif
|
||||
#ifdef FQDN
|
||||
sudo_inttable[I_FLAGS] |= FL_FQDN;
|
||||
#endif
|
||||
#ifdef USE_INSULTS
|
||||
sudo_inttable[I_FLAGS] |= FL_INSULTS;
|
||||
#endif
|
||||
|
||||
/* Then initialize the ints. */
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
sudo_inttable[I_LOGFAC] = LOGFAC;
|
||||
sudo_inttable[I_GOODPRI] = PRI_SUCCESS;
|
||||
sudo_inttable[I_BADPRI] = PRI_FAILURE;
|
||||
#else
|
||||
sudo_inttable[I_LOGFAC] = (unsigned int)-1;
|
||||
#endif
|
||||
#ifdef SUDO_UMASK
|
||||
sudo_inttable[I_UMASK] = SUDO_UMASK;
|
||||
#else
|
||||
sudo_inttable[I_UMASK] = 0777;
|
||||
#endif
|
||||
sudo_inttable[I_LOGLEN] = MAXLOGFILELEN;
|
||||
sudo_inttable[I_TS_TIMEOUT] = TIMEOUT;
|
||||
sudo_inttable[I_PW_TIMEOUT] = PASSWORD_TIMEOUT;
|
||||
sudo_inttable[I_PW_TRIES] = TRIES_FOR_PASSWORD;
|
||||
|
||||
/* Finally do the strings */
|
||||
sudo_strtable[I_ALERTMAIL] = estrdup(ALERTMAIL);
|
||||
sudo_strtable[I_MAILSUB] = estrdup(MAILSUBJECT);
|
||||
sudo_strtable[I_BADPASS_MSG] = estrdup(INCORRECT_PASSWORD);
|
||||
sudo_strtable[I_TIMESTAMPDIR] = estrdup(_PATH_SUDO_TIMEDIR);
|
||||
sudo_strtable[I_PASSPROMPT] = estrdup(PASSPROMPT);
|
||||
sudo_strtable[I_RUNAS_DEF] = estrdup(RUNAS_DEFAULT);
|
||||
#ifdef _PATH_SENDMAIL
|
||||
sudo_strtable[I_MAILERPATH] = estrdup(_PATH_SENDMAIL);
|
||||
#endif
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
sudo_strtable[I_LOGFILE] = estrdup(_PATH_SUDO_LOGFILE);
|
||||
#endif
|
||||
#ifdef EXEMPTGROUP
|
||||
sudo_strtable[I_EXEMPT_GRP] = estrdup(EXEMPTGROUP);
|
||||
#endif
|
||||
#ifdef SECURE_PATH
|
||||
sudo_strtable[I_SECURE_PATH] = estrdup(SECURE_PATH);
|
||||
#endif
|
||||
#if 0
|
||||
/* XXX - implement */
|
||||
sudo_strtable[I_MAILERARGS] = estrdup(XXX);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The following depend on the above values.
|
||||
* We use a pointer to the string so that if its
|
||||
* value changes we get the change.
|
||||
*/
|
||||
if (user_runas == NULL)
|
||||
user_runas = &sudo_strtable[I_RUNAS_DEF];
|
||||
|
||||
firsttime = 0;
|
||||
}
|
||||
|
||||
static int
|
||||
store_int(val, index, op)
|
||||
char *val;
|
||||
int index;
|
||||
int op;
|
||||
{
|
||||
char *endp;
|
||||
unsigned long ul;
|
||||
|
||||
if (op == FALSE) {
|
||||
sudo_inttable[index] = 0;
|
||||
} else {
|
||||
ul = strtoul(val, &endp, 10);
|
||||
if (*endp != '\0')
|
||||
return(FALSE);
|
||||
/* XXX - should check against UINT_MAX */
|
||||
sudo_inttable[index] = (unsigned int)ul;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
store_str(val, index, op)
|
||||
char *val;
|
||||
int index;
|
||||
int op;
|
||||
{
|
||||
|
||||
if (sudo_strtable[index])
|
||||
free(sudo_strtable[index]);
|
||||
if (op == FALSE)
|
||||
sudo_strtable[index] = NULL;
|
||||
else
|
||||
sudo_strtable[index] = estrdup(val);
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
store_syslogfac(val, index, op)
|
||||
char *val;
|
||||
int index;
|
||||
int op;
|
||||
{
|
||||
struct strmap *fac;
|
||||
|
||||
if (op == FALSE) {
|
||||
sudo_inttable[index] = (unsigned int)-1;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
for (fac = facilities; fac->name && strcmp(val, fac->name); fac++)
|
||||
;
|
||||
if (fac->name == NULL)
|
||||
return(FALSE);
|
||||
sudo_inttable[index] = fac->num;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
store_syslogpri(val, index, op)
|
||||
char *val;
|
||||
int index;
|
||||
int op;
|
||||
{
|
||||
struct strmap *pri;
|
||||
|
||||
if (op == FALSE)
|
||||
return(FALSE);
|
||||
|
||||
for (pri = priorities; pri->name && strcmp(val, pri->name); pri++)
|
||||
;
|
||||
if (pri->name == NULL)
|
||||
return(FALSE);
|
||||
sudo_inttable[index] = pri->num;
|
||||
return(TRUE);
|
||||
}
|
||||
|
||||
static int
|
||||
store_umask(val, index, op)
|
||||
char *val;
|
||||
int index;
|
||||
int op;
|
||||
{
|
||||
char *endp;
|
||||
unsigned long ul;
|
||||
|
||||
if (op == FALSE) {
|
||||
sudo_inttable[index] = 0777;
|
||||
} else {
|
||||
ul = strtoul(val, &endp, 8);
|
||||
if (*endp != '\0' || ul >= 0777)
|
||||
return(FALSE);
|
||||
sudo_inttable[index] = (mode_t)ul;
|
||||
}
|
||||
return(TRUE);
|
||||
}
|
117
defaults.h
Normal file
117
defaults.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 1999 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "Sudo" nor
|
||||
* may "Sudo" appear in their names without specific prior written
|
||||
* permission from the author.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* $Sudo$
|
||||
*/
|
||||
|
||||
#ifndef _SUDO_DEFAULTS_H
|
||||
#define _SUDO_DEFAULTS_H
|
||||
|
||||
/*
|
||||
* Four types of defaults: strings, integers, booleans, and flags.
|
||||
* Note that flags have their value in the index field.
|
||||
* Also, T_INT or T_STR may be ANDed with T_BOOL to indicate that
|
||||
* a value is not required.
|
||||
*/
|
||||
#define T_INT 0x01
|
||||
#define T_STR 0x02
|
||||
#define T_FLAG 0x08
|
||||
#define T_MASK 0x0F
|
||||
#define T_BOOL 0x10
|
||||
|
||||
/*
|
||||
* Flag values
|
||||
*/
|
||||
#define FL_LONG_OTP_PROMPT 0x00001
|
||||
#define FL_IGNORE_DOT 0x00002
|
||||
#define FL_MAIL_ALWAYS 0x00004
|
||||
#define FL_MAIL_IF_NOUSER 0x00008
|
||||
#define FL_MAIL_IF_NOHOST 0x00010
|
||||
#define FL_MAIL_IF_NOPERMS 0x00020
|
||||
#define FL_TTY_TICKETS 0x00040
|
||||
#define FL_LECTURE 0x00080
|
||||
#define FL_AUTHENTICATE 0x00100
|
||||
#define FL_ROOT_SUDO 0x00200
|
||||
#define FL_LOG_HOST 0x00400
|
||||
#define FL_SHELL_NOARGS 0x00800
|
||||
#define FL_SET_HOME 0x01000
|
||||
#define FL_PATH_INFO 0x02000
|
||||
#define FL_FQDN 0x04000
|
||||
#define FL_INSULTS 0x08000
|
||||
#define FL_MAX 0xFFFFF
|
||||
|
||||
/*
|
||||
* Indexes into sudo_inttable
|
||||
*/
|
||||
#define I_FLAGS 0 /* various flags, as listed above */
|
||||
#define I_LOGFAC 1 /* syslog facility */
|
||||
#define I_GOODPRI 2 /* syslog priority for successful auth */
|
||||
#define I_BADPRI 3 /* syslog priority for unsuccessful auth */
|
||||
#define I_LOGLEN 4 /* wrap log file line after N chars */
|
||||
#define I_TS_TIMEOUT 5 /* timestamp stale after N minutes */
|
||||
#define I_PW_TIMEOUT 6 /* exit if pass not entered in N minutes */
|
||||
#define I_PW_TRIES 7 /* exit after N bad password tries */
|
||||
#define I_UMASK 8 /* umask to use or 0777 to use user's */
|
||||
|
||||
/*
|
||||
* Indexes into sudo_strtable
|
||||
*/
|
||||
#define I_LOGFILE 0 /* path to logfile (or NULL for none) */
|
||||
#define I_MAILERPATH 1 /* path to sendmail or other mailer */
|
||||
#define I_MAILERARGS 2 /* flags to pass to the mailer */
|
||||
#define I_ALERTMAIL 3 /* who to send bitch mail to */
|
||||
#define I_MAILSUB 4 /* subject line of mail msg */
|
||||
#define I_BADPASS_MSG 5 /* what to say when passwd is wrong */
|
||||
#define I_TIMESTAMPDIR 6 /* path to timestamp dir */
|
||||
#define I_EXEMPT_GRP 7 /* no password or PATH override for these */
|
||||
#define I_PASSPROMPT 8 /* password prompt */
|
||||
#define I_RUNAS_DEF 9 /* default user to run commands as */
|
||||
#define I_SECURE_PATH 10 /* set $PATH to this if not NULL */
|
||||
|
||||
#define SUDO_INTTABLE_LAST 9
|
||||
#define SUDO_STRTABLE_LAST 11
|
||||
|
||||
#define sudo_flag_set(_f) (sudo_inttable[I_FLAGS] & (_f))
|
||||
|
||||
extern unsigned int sudo_inttable[SUDO_INTTABLE_LAST];
|
||||
extern char *sudo_strtable[SUDO_STRTABLE_LAST];
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
void dump_default __P((void));
|
||||
int set_default __P((char *, char *, int));
|
||||
void init_defaults __P((void));
|
||||
void list_options __P((void));
|
||||
|
||||
#endif /* _SUDO_DEFAULTS_H */
|
13
find_path.c
13
find_path.c
@@ -72,7 +72,7 @@ static const char rcsid[] = "$Sudo$";
|
||||
* stores it in a statically allocated array, filling in a pointer
|
||||
* to the array. Returns FOUND if the command was found, NOT_FOUND
|
||||
* if it was not found, or NOT_FOUND_DOT if it would have been found
|
||||
* but it is in '.' and IGNORE_DOT_PATH is in effect.
|
||||
* but it is in '.' and FL_IGNORE_DOT is set.
|
||||
*/
|
||||
int
|
||||
find_path(infile, outfile)
|
||||
@@ -105,9 +105,12 @@ find_path(infile, outfile)
|
||||
}
|
||||
|
||||
/*
|
||||
* Grab PATH out of environment and make a local copy
|
||||
* Grab PATH out of the environment (or from the string table
|
||||
* if SECURE_PATH is in effect) and make a local copy.
|
||||
*/
|
||||
if ((path = getenv("PATH")) == NULL)
|
||||
if (sudo_strtable[I_SECURE_PATH])
|
||||
path = sudo_strtable[I_SECURE_PATH];
|
||||
else if ((path = getenv("PATH")) == NULL)
|
||||
return(NOT_FOUND);
|
||||
path = estrdup(path);
|
||||
origpath = path;
|
||||
@@ -147,10 +150,8 @@ find_path(infile, outfile)
|
||||
*/
|
||||
if (!result && checkdot) {
|
||||
result = sudo_goodpath(infile);
|
||||
#ifdef IGNORE_DOT_PATH
|
||||
if (result)
|
||||
if (result && sudo_flag_set(FL_IGNORE_DOT))
|
||||
return(NOT_FOUND_DOT);
|
||||
#endif /* IGNORE_DOT_PATH */
|
||||
}
|
||||
|
||||
if (result) {
|
||||
|
213
logging.c
213
logging.c
@@ -62,19 +62,14 @@
|
||||
static const char rcsid[] = "$Sudo$";
|
||||
#endif /* lint */
|
||||
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
static void do_syslog __P((int, char *));
|
||||
#endif
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
static void do_logfile __P((char *));
|
||||
#endif
|
||||
static void send_mail __P((char *));
|
||||
static void mail_auth __P((int, char *));
|
||||
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
# ifdef BROKEN_SYSLOG
|
||||
# define MAXSYSLOGTRIES 16 /* num of retries for broken syslogs */
|
||||
# define SYSLOG syslog_wrapper
|
||||
#ifdef BROKEN_SYSLOG
|
||||
# define MAXSYSLOGTRIES 16 /* num of retries for broken syslogs */
|
||||
# define SYSLOG syslog_wrapper
|
||||
|
||||
static void syslog_wrapper __P((int, char *, char *, char *));
|
||||
|
||||
@@ -95,9 +90,9 @@ syslog_wrapper(pri, fmt, ap)
|
||||
if (vsyslog(pri, fmt, ap) == 0)
|
||||
break;
|
||||
}
|
||||
# else
|
||||
# define SYSLOG syslog
|
||||
# endif /* BROKEN_SYSLOG */
|
||||
#else
|
||||
# define SYSLOG syslog
|
||||
#endif /* BROKEN_SYSLOG */
|
||||
|
||||
/*
|
||||
* Log a message to syslog, pre-pending the username and splitting the
|
||||
@@ -149,9 +144,7 @@ do_syslog(pri, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* LOGGING & SLOG_SYSLOG */
|
||||
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
static void
|
||||
do_logfile(msg)
|
||||
char *msg;
|
||||
@@ -161,96 +154,94 @@ do_logfile(msg)
|
||||
FILE *fp;
|
||||
mode_t oldmask;
|
||||
time_t now;
|
||||
int maxlen = MAXLOGFILELEN;
|
||||
int maxlen = sudo_inttable[I_LOGLEN];
|
||||
|
||||
now = time((time_t) 0);
|
||||
|
||||
oldmask = umask(077);
|
||||
fp = fopen(_PATH_SUDO_LOGFILE, "a");
|
||||
fp = fopen(sudo_strtable[I_LOGFILE], "a");
|
||||
(void) umask(oldmask);
|
||||
if (fp == NULL) {
|
||||
easprintf(&full_line, "Can't open log file: %s: %s",
|
||||
_PATH_SUDO_LOGFILE, strerror(errno));
|
||||
sudo_strtable[I_LOGFILE], strerror(errno));
|
||||
send_mail(full_line);
|
||||
free(full_line);
|
||||
} else if (!lock_file(fileno(fp), SUDO_LOCK)) {
|
||||
easprintf(&full_line, "Can't lock log file: %s: %s",
|
||||
_PATH_SUDO_LOGFILE, strerror(errno));
|
||||
sudo_strtable[I_LOGFILE], strerror(errno));
|
||||
send_mail(full_line);
|
||||
free(full_line);
|
||||
} else {
|
||||
# ifndef WRAP_LOG
|
||||
# ifdef HOST_IN_LOG
|
||||
(void) fprintf(fp, "%15.15s : %s : HOST=%s : %s\n", ctime(&now) + 4,
|
||||
user_name, user_shost, msg);
|
||||
# else
|
||||
(void) fprintf(fp, "%15.15s : %s : %s\n", ctime(&now) + 4, user_name,
|
||||
msg);
|
||||
# endif
|
||||
# else
|
||||
# ifdef HOST_IN_LOG
|
||||
easprintf(&full_line, "%15.15s : %s : HOST=%s : %s",
|
||||
ctime(&now) + 4, user_name, user_shost, msg);
|
||||
# else
|
||||
easprintf(&full_line, "%15.15s : %s : %s", ctime(&now) + 4,
|
||||
user_name, msg);
|
||||
# endif
|
||||
if (sudo_inttable[I_LOGLEN] == 0) {
|
||||
/* Don't pretty-print long log file lines (hard to grep) */
|
||||
if (sudo_flag_set(FL_LOG_HOST))
|
||||
(void) fprintf(fp, "%15.15s : %s : HOST=%s : %s\n",
|
||||
ctime(&now) + 4, user_name, user_shost, msg);
|
||||
else
|
||||
(void) fprintf(fp, "%15.15s : %s : %s\n", ctime(&now) + 4,
|
||||
user_name, msg);
|
||||
} else {
|
||||
if (sudo_flag_set(FL_LOG_HOST))
|
||||
easprintf(&full_line, "%15.15s : %s : HOST=%s : %s",
|
||||
ctime(&now) + 4, user_name, user_shost, msg);
|
||||
else
|
||||
easprintf(&full_line, "%15.15s : %s : %s", ctime(&now) + 4,
|
||||
user_name, msg);
|
||||
|
||||
/*
|
||||
* Print out full_line with word wrap
|
||||
*/
|
||||
beg = end = full_line;
|
||||
while (beg) {
|
||||
oldend = end;
|
||||
end = strchr(oldend, ' ');
|
||||
/*
|
||||
* Print out full_line with word wrap
|
||||
*/
|
||||
beg = end = full_line;
|
||||
while (beg) {
|
||||
oldend = end;
|
||||
end = strchr(oldend, ' ');
|
||||
|
||||
if (maxlen > 0 && end) {
|
||||
*end = '\0';
|
||||
if (strlen(beg) > maxlen) {
|
||||
/* too far, need to back up & print the line */
|
||||
if (maxlen > 0 && end) {
|
||||
*end = '\0';
|
||||
if (strlen(beg) > maxlen) {
|
||||
/* too far, need to back up & print the line */
|
||||
|
||||
if (beg == (char *)full_line)
|
||||
maxlen -= 4; /* don't indent first line */
|
||||
if (beg == (char *)full_line)
|
||||
maxlen -= 4; /* don't indent first line */
|
||||
|
||||
*end = ' ';
|
||||
if (oldend != beg) {
|
||||
/* rewind & print */
|
||||
end = oldend-1;
|
||||
while (*end == ' ')
|
||||
--end;
|
||||
*(++end) = '\0';
|
||||
(void) fprintf(fp, "%s\n ", beg);
|
||||
*end = ' ';
|
||||
if (oldend != beg) {
|
||||
/* rewind & print */
|
||||
end = oldend-1;
|
||||
while (*end == ' ')
|
||||
--end;
|
||||
*(++end) = '\0';
|
||||
(void) fprintf(fp, "%s\n ", beg);
|
||||
*end = ' ';
|
||||
} else {
|
||||
(void) fprintf(fp, "%s\n ", beg);
|
||||
}
|
||||
|
||||
/* reset beg to point to the start of the new substr */
|
||||
beg = end;
|
||||
while (*beg == ' ')
|
||||
++beg;
|
||||
} else {
|
||||
(void) fprintf(fp, "%s\n ", beg);
|
||||
/* we still have room */
|
||||
*end = ' ';
|
||||
}
|
||||
|
||||
/* reset beg to point to the start of the new substring */
|
||||
beg = end;
|
||||
while (*beg == ' ')
|
||||
++beg;
|
||||
/* remove leading whitespace */
|
||||
while (*end == ' ')
|
||||
++end;
|
||||
} else {
|
||||
/* we still have room */
|
||||
*end = ' ';
|
||||
/* final line */
|
||||
(void) fprintf(fp, "%s\n", beg);
|
||||
beg = NULL; /* exit condition */
|
||||
}
|
||||
|
||||
/* remove leading whitespace */
|
||||
while (*end == ' ')
|
||||
++end;
|
||||
} else {
|
||||
/* final line */
|
||||
(void) fprintf(fp, "%s\n", beg);
|
||||
beg = NULL; /* exit condition */
|
||||
}
|
||||
free(full_line);
|
||||
}
|
||||
free(full_line);
|
||||
# endif
|
||||
(void) fflush(fp);
|
||||
(void) lock_file(fileno(fp), SUDO_UNLOCK);
|
||||
(void) fclose(fp);
|
||||
}
|
||||
}
|
||||
#endif /* LOGGING & SLOG_FILE */
|
||||
|
||||
/*
|
||||
* Two main functions, log_error() to log errors and log_auth() to
|
||||
@@ -263,14 +254,12 @@ log_auth(status, inform_user)
|
||||
{
|
||||
char *message;
|
||||
char *logline;
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
int pri;
|
||||
|
||||
if (status & VALIDATE_OK)
|
||||
pri = PRI_SUCCESS;
|
||||
else
|
||||
pri = PRI_FAILURE;
|
||||
#endif /* LOGGING & SLOG_SYSLOG */
|
||||
|
||||
/* Set error message, if any. */
|
||||
if (status & VALIDATE_OK)
|
||||
@@ -285,7 +274,7 @@ log_auth(status, inform_user)
|
||||
message = "unknown error ; ";
|
||||
|
||||
easprintf(&logline, "%sTTY=%s ; PWD=%s ; USER=%s ; COMMAND=%s%s%s",
|
||||
message, user_tty, user_cwd, user_runas, user_cmnd,
|
||||
message, user_tty, user_cwd, *user_runas, user_cmnd,
|
||||
user_args ? " " : "", user_args ? user_args : "");
|
||||
|
||||
mail_auth(status, logline); /* send mail based on status */
|
||||
@@ -305,18 +294,16 @@ log_auth(status, inform_user)
|
||||
(void) fprintf(stderr,
|
||||
"Sorry, user %s is not allowed to execute '%s%s%s' as %s on %s.\n",
|
||||
user_name, user_cmnd, user_args ? " " : "",
|
||||
user_args ? user_args : "", user_runas, user_host);
|
||||
user_args ? user_args : "", *user_runas, user_host);
|
||||
}
|
||||
|
||||
/*
|
||||
* Log via syslog and/or a file.
|
||||
*/
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
do_syslog(pri, logline);
|
||||
#endif
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
do_logfile(logline);
|
||||
#endif
|
||||
if (sudo_inttable[I_LOGFAC] != (unsigned int)-1)
|
||||
do_syslog(pri, logline);
|
||||
if (sudo_strtable[I_LOGFILE])
|
||||
do_logfile(logline);
|
||||
|
||||
free(logline);
|
||||
}
|
||||
@@ -358,22 +345,22 @@ log_error(va_alist)
|
||||
if (user_args) {
|
||||
easprintf(&logline,
|
||||
"%s: %s ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=%s %s",
|
||||
message, strerror(serrno), user_tty, user_cwd, user_runas,
|
||||
message, strerror(serrno), user_tty, user_cwd, *user_runas,
|
||||
user_cmnd, user_args);
|
||||
} else {
|
||||
easprintf(&logline,
|
||||
"%s: %s ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=%s", message,
|
||||
strerror(serrno), user_tty, user_cwd, user_runas, user_cmnd);
|
||||
strerror(serrno), user_tty, user_cwd, *user_runas, user_cmnd);
|
||||
}
|
||||
} else {
|
||||
if (user_args) {
|
||||
easprintf(&logline,
|
||||
"%s ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=%s %s", message,
|
||||
user_tty, user_cwd, user_runas, user_cmnd, user_args);
|
||||
user_tty, user_cwd, *user_runas, user_cmnd, user_args);
|
||||
} else {
|
||||
easprintf(&logline,
|
||||
"%s ; TTY=%s ; PWD=%s ; USER=%s ; COMMAND=%s", message,
|
||||
user_tty, user_cwd, user_runas, user_cmnd);
|
||||
user_tty, user_cwd, *user_runas, user_cmnd);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -394,12 +381,10 @@ log_error(va_alist)
|
||||
/*
|
||||
* Log to syslog and/or a file.
|
||||
*/
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
do_syslog(PRI_FAILURE, logline);
|
||||
#endif
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
do_logfile(logline);
|
||||
#endif
|
||||
if (sudo_inttable[I_LOGFAC] != (unsigned int)-1)
|
||||
do_syslog(PRI_FAILURE, logline);
|
||||
if (sudo_strtable[I_LOGFILE])
|
||||
do_logfile(logline);
|
||||
|
||||
free(logline);
|
||||
if (message != logline);
|
||||
@@ -409,7 +394,6 @@ log_error(va_alist)
|
||||
/*
|
||||
* Send a message to ALERTMAIL
|
||||
*/
|
||||
#ifdef _PATH_SENDMAIL
|
||||
static void
|
||||
send_mail(line)
|
||||
char *line;
|
||||
@@ -419,6 +403,10 @@ send_mail(line)
|
||||
int pfd[2], pid;
|
||||
time_t now;
|
||||
|
||||
/* Just return if mailer is disabled. */
|
||||
if (!sudo_strtable[I_MAILERPATH])
|
||||
return;
|
||||
|
||||
if ((pid = fork()) > 0) { /* Child. */
|
||||
|
||||
/* We do an explicit wait() later on... */
|
||||
@@ -456,9 +444,9 @@ send_mail(line)
|
||||
(void) close(pfd[0]);
|
||||
|
||||
/* Pipes are all setup, send message via sendmail. */
|
||||
(void) fprintf(mail, "To: %s\nFrom: %s\nSubject: ", ALERTMAIL,
|
||||
user_name);
|
||||
for (p = MAILSUBJECT; *p; p++) {
|
||||
(void) fprintf(mail, "To: %s\nFrom: %s\nSubject: ",
|
||||
sudo_strtable[I_ALERTMAIL], user_name);
|
||||
for (p = sudo_strtable[I_MAILSUB]; *p; p++) {
|
||||
/* Expand escapes in the subject */
|
||||
if (*p == '%' && *(p+1) != '%') {
|
||||
switch (*(++p)) {
|
||||
@@ -491,14 +479,6 @@ send_mail(line)
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
static void
|
||||
send_mail(line)
|
||||
char *line;
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Send mail based on the value of "status" and compile-time options.
|
||||
@@ -511,19 +491,18 @@ mail_auth(status, line)
|
||||
int mail_mask;
|
||||
|
||||
/* If any of these bits are set in status, we send mail. */
|
||||
mail_mask = VALIDATE_ERROR;
|
||||
#ifdef SEND_MAIL_WHEN_OK
|
||||
mail_mask |= VALIDATE_OK;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NO_USER
|
||||
mail_mask |= FLAG_NO_USER;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NO_HOST
|
||||
mail_mask |= FLAG_NO_HOST;
|
||||
#endif
|
||||
#ifdef SEND_MAIL_WHEN_NOT_OK
|
||||
mail_mask |= VALIDATE_NOT_OK;
|
||||
#endif
|
||||
if (sudo_flag_set(FL_MAIL_ALWAYS))
|
||||
mail_mask =
|
||||
VALIDATE_ERROR|VALIDATE_OK|FLAG_NO_USER|FLAG_NO_HOST|VALIDATE_NOT_OK;
|
||||
else {
|
||||
mail_mask = VALIDATE_ERROR;
|
||||
if (sudo_flag_set(FL_MAIL_IF_NOUSER))
|
||||
mail_mask |= FLAG_NO_USER;
|
||||
if (sudo_flag_set(FL_MAIL_IF_NOHOST))
|
||||
mail_mask |= FLAG_NO_HOST;
|
||||
if (sudo_flag_set(FL_MAIL_IF_NOPERMS))
|
||||
mail_mask |= VALIDATE_NOT_OK;
|
||||
}
|
||||
|
||||
if ((status & mail_mask) != 0)
|
||||
send_mail(line);
|
||||
|
8
parse.h
8
parse.h
@@ -104,4 +104,12 @@ struct generic_alias {
|
||||
extern struct matchstack *match;
|
||||
extern int top;
|
||||
|
||||
/*
|
||||
* Prototypes
|
||||
*/
|
||||
int addr_matches __P((char *));
|
||||
int command_matches __P((char *, char *, char *, char *));
|
||||
int netgr_matches __P((char *, char *, char *));
|
||||
int usergr_matches __P((char *, char *));
|
||||
|
||||
#endif /* _SUDO_PARSE_H */
|
||||
|
126
parse.lex
126
parse.lex
@@ -93,7 +93,7 @@ extern void yyerror __P((char *));
|
||||
OCTET (1?[0-9]{1,2})|(2[0-4][0-9])|(25[0-5])
|
||||
DOTTEDQUAD {OCTET}(\.{OCTET}){3}
|
||||
HOSTNAME [[:alnum:]_-]+
|
||||
USERNAME [^:,\) \t\n]+
|
||||
WORD [^@!=:,\(\) \t\n\\]+
|
||||
|
||||
%e 4000
|
||||
%p 6000
|
||||
@@ -101,6 +101,7 @@ USERNAME [^:,\) \t\n]+
|
||||
|
||||
%s GOTCMND
|
||||
%s GOTRUNAS
|
||||
%s GOTDEFS
|
||||
|
||||
%%
|
||||
[ \t]+ { /* throw away space/tabs */
|
||||
@@ -113,12 +114,26 @@ USERNAME [^:,\) \t\n]+
|
||||
LEXTRACE("\n\t");
|
||||
} /* throw away EOL after \ */
|
||||
|
||||
<GOTCMND>\\[:\,=\\ \t] {
|
||||
<GOTCMND>\\[@:\,=\\ \t] {
|
||||
LEXTRACE("QUOTEDCHAR ");
|
||||
fill_args(yytext + 1, 1, sawspace);
|
||||
sawspace = FALSE;
|
||||
}
|
||||
|
||||
<GOTDEFS>\"[^\"]+\" {
|
||||
/* XXX - should allow " to be quoted */
|
||||
LEXTRACE("WORD(1) ");
|
||||
fill(yytext + 1, yyleng - 2);
|
||||
return(WORD);
|
||||
}
|
||||
|
||||
<GOTDEFS>(#.*)?\n {
|
||||
BEGIN INITIAL;
|
||||
++sudolineno;
|
||||
LEXTRACE("\n");
|
||||
return(COMMENT);
|
||||
}
|
||||
|
||||
<GOTCMND>[:\,=\n] {
|
||||
BEGIN INITIAL;
|
||||
unput(*yytext);
|
||||
@@ -175,15 +190,17 @@ PASSWD[[:blank:]]*: {
|
||||
return(PASSWD);
|
||||
}
|
||||
|
||||
\+{USERNAME} {
|
||||
\+{WORD} {
|
||||
/* netgroup */
|
||||
fill(yytext, yyleng);
|
||||
LEXTRACE("NETGROUP ");
|
||||
return(NETGROUP);
|
||||
}
|
||||
|
||||
\%{USERNAME} {
|
||||
\%{WORD} {
|
||||
/* UN*X group */
|
||||
fill(yytext, yyleng);
|
||||
LEXTRACE("GROUP ");
|
||||
return(USERGROUP);
|
||||
}
|
||||
|
||||
@@ -223,15 +240,71 @@ PASSWD[[:blank:]]*: {
|
||||
}
|
||||
}
|
||||
|
||||
<GOTRUNAS>#?{USERNAME} {
|
||||
<GOTRUNAS>#?{WORD} {
|
||||
/* username/uid that user can run command as */
|
||||
fill(yytext, yyleng);
|
||||
LEXTRACE("NAME ");
|
||||
return(NAME);
|
||||
LEXTRACE("WORD(2) ");
|
||||
return(WORD);
|
||||
}
|
||||
|
||||
<GOTRUNAS>\) BEGIN INITIAL;
|
||||
<GOTRUNAS>\) {
|
||||
BEGIN INITIAL;
|
||||
}
|
||||
|
||||
[[:upper:]][[:upper:][:digit:]_]* {
|
||||
if (strcmp(yytext, "ALL") == 0) {
|
||||
LEXTRACE("ALL ");
|
||||
return(ALL);
|
||||
} else {
|
||||
fill(yytext, yyleng);
|
||||
LEXTRACE("ALIAS ");
|
||||
return(ALIAS);
|
||||
}
|
||||
}
|
||||
|
||||
<GOTDEFS>[^ \t\n,=!]+ {
|
||||
/* XXX - should allow [!=,] to be quoted */
|
||||
LEXTRACE("WORD(3) ");
|
||||
fill(yytext, yyleng);
|
||||
return(WORD);
|
||||
}
|
||||
|
||||
<INITIAL>^Defaults[:@]? {
|
||||
BEGIN GOTDEFS;
|
||||
if (yyleng == 9) {
|
||||
switch (yytext[8]) {
|
||||
case ':' :
|
||||
LEXTRACE("DEFAULTS_USER ");
|
||||
return(DEFAULTS_USER);
|
||||
case '@' :
|
||||
LEXTRACE("DEFAULTS_HOST ");
|
||||
return(DEFAULTS_HOST);
|
||||
}
|
||||
} else {
|
||||
LEXTRACE("DEFAULTS ");
|
||||
return(DEFAULTS);
|
||||
}
|
||||
}
|
||||
|
||||
<INITIAL>^(Host|Cmnd|User|Runas)_Alias {
|
||||
fill(yytext, yyleng);
|
||||
if (*yytext == 'H') {
|
||||
LEXTRACE("HOSTALIAS ");
|
||||
return(HOSTALIAS);
|
||||
}
|
||||
if (*yytext == 'C') {
|
||||
LEXTRACE("CMNDALIAS ");
|
||||
return(CMNDALIAS);
|
||||
}
|
||||
if (*yytext == 'U') {
|
||||
LEXTRACE("USERALIAS ");
|
||||
return(USERALIAS);
|
||||
}
|
||||
if (*yytext == 'R') {
|
||||
LEXTRACE("RUNASALIAS ");
|
||||
return(RUNASALIAS);
|
||||
}
|
||||
}
|
||||
|
||||
\/[^\,:=\\ \t\n#]+ {
|
||||
/* directories can't have args... */
|
||||
@@ -246,42 +319,15 @@ PASSWD[[:blank:]]*: {
|
||||
}
|
||||
} /* a pathname */
|
||||
|
||||
[[:upper:]][[:upper:][:digit:]_]* {
|
||||
if (strcmp(yytext, "ALL") == 0) {
|
||||
LEXTRACE("ALL ");
|
||||
return(ALL);
|
||||
} else {
|
||||
fill(yytext, yyleng);
|
||||
LEXTRACE("ALIAS ");
|
||||
return(ALIAS);
|
||||
}
|
||||
}
|
||||
|
||||
[[:alnum:]][[:alnum:]_-]* {
|
||||
{WORD} {
|
||||
/* a word */
|
||||
fill(yytext, yyleng);
|
||||
if (strcmp(yytext, "Host_Alias") == 0) {
|
||||
LEXTRACE("HOSTALIAS ");
|
||||
return(HOSTALIAS);
|
||||
}
|
||||
if (strcmp(yytext, "Cmnd_Alias") == 0) {
|
||||
LEXTRACE("CMNDALIAS ");
|
||||
return(CMNDALIAS);
|
||||
}
|
||||
if (strcmp(yytext, "User_Alias") == 0) {
|
||||
LEXTRACE("USERALIAS ");
|
||||
return(USERALIAS);
|
||||
}
|
||||
if (strcmp(yytext, "Runas_Alias") == 0) {
|
||||
LEXTRACE("RUNASALIAS ");
|
||||
return(RUNASALIAS);
|
||||
}
|
||||
|
||||
/* NAME is what RFC1034 calls a label */
|
||||
LEXTRACE("NAME ");
|
||||
return(NAME);
|
||||
LEXTRACE("WORD(4) ");
|
||||
return(WORD);
|
||||
}
|
||||
|
||||
. {
|
||||
LEXTRACE("ERROR ");
|
||||
return(ERROR);
|
||||
} /* parse error */
|
||||
|
||||
|
99
parse.yacc
99
parse.yacc
@@ -90,11 +90,6 @@ int errorlineno = -1;
|
||||
int clearaliases = TRUE;
|
||||
int printmatches = FALSE;
|
||||
int pedantic = FALSE;
|
||||
#ifdef NO_AUTHENTICATION
|
||||
int pwdef = TRUE;
|
||||
#else
|
||||
int pwdef = -1;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Alias types
|
||||
@@ -120,7 +115,7 @@ int top = 0, stacksize = 0;
|
||||
match[top].cmnd = -1; \
|
||||
match[top].host = -1; \
|
||||
match[top].runas = -1; \
|
||||
match[top].nopass = pwdef; \
|
||||
match[top].nopass = sudo_flag_set(FL_AUTHENTICATE) ? -1 : TRUE; \
|
||||
top++; \
|
||||
} while (0)
|
||||
|
||||
@@ -173,12 +168,13 @@ static size_t ga_list_len = 0, ga_list_size = 0;
|
||||
static struct generic_alias *ga_list = NULL;
|
||||
|
||||
/*
|
||||
* Protoypes
|
||||
* Does this Defaults list pertain to this user?
|
||||
*/
|
||||
static int defaults_matches = 0;
|
||||
|
||||
/*
|
||||
* Local protoypes
|
||||
*/
|
||||
extern int addr_matches __P((char *));
|
||||
extern int command_matches __P((char *, char *, char *, char *));
|
||||
extern int netgr_matches __P((char *, char *, char *));
|
||||
extern int usergr_matches __P((char *, char *));
|
||||
static int add_alias __P((char *, int, int));
|
||||
static void append __P((char *, char **, size_t *, size_t *, char *));
|
||||
static void expand_ga_list __P((void));
|
||||
@@ -221,7 +217,10 @@ yyerror(s)
|
||||
%token <string> FQHOST /* foo.bar.com */
|
||||
%token <string> NETGROUP /* a netgroup (+NAME) */
|
||||
%token <string> USERGROUP /* a usergroup (%NAME) */
|
||||
%token <string> NAME /* a mixed-case name */
|
||||
%token <string> WORD /* a word */
|
||||
%token <tok> DEFAULTS /* Defaults entry */
|
||||
%token <tok> DEFAULTS_HOST /* Host-specific defaults entry */
|
||||
%token <tok> DEFAULTS_USER /* User-specific defaults entry */
|
||||
%token <tok> RUNAS /* ( runas_list ) */
|
||||
%token <tok> NOPASSWD /* no passwd req for command */
|
||||
%token <tok> PASSWD /* passwd req for command (default) */
|
||||
@@ -267,8 +266,51 @@ entry : COMMENT
|
||||
{ ; }
|
||||
| RUNASALIAS runasaliases
|
||||
{ ; }
|
||||
| defaults_line
|
||||
{ ; }
|
||||
;
|
||||
|
||||
defaults_line : defaults_type defaults_list
|
||||
|
||||
defaults_type : DEFAULTS {
|
||||
defaults_matches = TRUE;
|
||||
}
|
||||
| DEFAULTS_USER { push; } userlist {
|
||||
defaults_matches = user_matches;
|
||||
pop;
|
||||
}
|
||||
| DEFAULTS_HOST { push; } hostlist {
|
||||
defaults_matches = host_matches;
|
||||
pop;
|
||||
}
|
||||
;
|
||||
|
||||
defaults_list : defaults_entry
|
||||
| defaults_entry ',' defaults_list
|
||||
|
||||
defaults_entry : WORD {
|
||||
if (defaults_matches && !set_default($1, NULL, 1)) {
|
||||
yyerror(NULL);
|
||||
YYERROR;
|
||||
}
|
||||
free($1);
|
||||
}
|
||||
| '!' WORD {
|
||||
if (defaults_matches && !set_default($2, NULL, 0)) {
|
||||
yyerror(NULL);
|
||||
YYERROR;
|
||||
}
|
||||
free($2);
|
||||
}
|
||||
| WORD '=' WORD {
|
||||
/* XXX - need to support quoted values */
|
||||
if (defaults_matches && !set_default($1, $3, 1)) {
|
||||
yyerror(NULL);
|
||||
YYERROR;
|
||||
}
|
||||
free($1);
|
||||
free($3);
|
||||
}
|
||||
|
||||
privileges : privilege
|
||||
| privileges ':' privilege
|
||||
@@ -282,7 +324,10 @@ privilege : hostlist '=' cmndspeclist {
|
||||
*/
|
||||
host_matches = -1;
|
||||
runas_matches = -1;
|
||||
no_passwd = pwdef;
|
||||
if (sudo_flag_set(FL_AUTHENTICATE))
|
||||
no_passwd = -1;
|
||||
else
|
||||
no_passwd = TRUE;
|
||||
}
|
||||
;
|
||||
|
||||
@@ -312,7 +357,7 @@ host : ALL {
|
||||
$$ = -1;
|
||||
free($1);
|
||||
}
|
||||
| NAME {
|
||||
| WORD {
|
||||
if (strcasecmp(user_shost, $1) == 0)
|
||||
$$ = TRUE;
|
||||
else
|
||||
@@ -411,11 +456,11 @@ runasspec : /* empty */ {
|
||||
}
|
||||
/*
|
||||
* If this is the first entry in a command list
|
||||
* then check against RUNAS_DEFAULT.
|
||||
* then check against default runas user.
|
||||
*/
|
||||
if (runas_matches == -1)
|
||||
runas_matches =
|
||||
(strcmp(RUNAS_DEFAULT, user_runas) == 0);
|
||||
runas_matches = (strcmp(*user_runas,
|
||||
sudo_strtable[I_RUNAS_DEF]) == 0);
|
||||
}
|
||||
| RUNAS runaslist { ; }
|
||||
;
|
||||
@@ -441,7 +486,7 @@ oprunasuser : runasuser {
|
||||
runas_matches = ! $3;
|
||||
}
|
||||
|
||||
runasuser : NAME {
|
||||
runasuser : WORD {
|
||||
if (printmatches == TRUE) {
|
||||
if (in_alias == TRUE)
|
||||
append_entries($1, ", ");
|
||||
@@ -449,7 +494,7 @@ runasuser : NAME {
|
||||
user_matches == TRUE)
|
||||
append_runas($1, ", ");
|
||||
}
|
||||
if (strcmp($1, user_runas) == 0)
|
||||
if (strcmp($1, *user_runas) == 0)
|
||||
$$ = TRUE;
|
||||
else
|
||||
$$ = -1;
|
||||
@@ -463,7 +508,7 @@ runasuser : NAME {
|
||||
user_matches == TRUE)
|
||||
append_runas($1, ", ");
|
||||
}
|
||||
if (usergr_matches($1, user_runas))
|
||||
if (usergr_matches($1, *user_runas))
|
||||
$$ = TRUE;
|
||||
else
|
||||
$$ = -1;
|
||||
@@ -477,7 +522,7 @@ runasuser : NAME {
|
||||
user_matches == TRUE)
|
||||
append_runas($1, ", ");
|
||||
}
|
||||
if (netgr_matches($1, NULL, user_runas))
|
||||
if (netgr_matches($1, NULL, *user_runas))
|
||||
$$ = TRUE;
|
||||
else
|
||||
$$ = -1;
|
||||
@@ -496,7 +541,7 @@ runasuser : NAME {
|
||||
/* could be an all-caps username */
|
||||
if (aip)
|
||||
$$ = aip->val;
|
||||
else if (strcmp($1, user_runas) == 0)
|
||||
else if (strcmp($1, *user_runas) == 0)
|
||||
$$ = TRUE;
|
||||
else {
|
||||
if (pedantic) {
|
||||
@@ -705,7 +750,7 @@ useralias : ALIAS { push; } '=' userlist {
|
||||
}
|
||||
;
|
||||
|
||||
userlist : opuser { ; }
|
||||
userlist : opuser
|
||||
| userlist ',' opuser
|
||||
;
|
||||
|
||||
@@ -718,7 +763,7 @@ opuser : user {
|
||||
user_matches = ! $2;
|
||||
}
|
||||
|
||||
user : NAME {
|
||||
user : WORD {
|
||||
if (strcmp($1, user_name) == 0)
|
||||
$$ = TRUE;
|
||||
else
|
||||
@@ -951,13 +996,13 @@ list_matches()
|
||||
} while ((p = strtok(NULL, ", ")));
|
||||
(void) fputs(") ", stdout);
|
||||
} else {
|
||||
(void) printf("(%s) ", RUNAS_DEFAULT);
|
||||
(void) printf("(%s) ", sudo_strtable[I_RUNAS_DEF]);
|
||||
}
|
||||
|
||||
/* Is a password required? */
|
||||
if (cm_list[i].nopasswd == TRUE && pwdef != TRUE)
|
||||
if (cm_list[i].nopasswd == TRUE && sudo_flag_set(FL_AUTHENTICATE))
|
||||
(void) fputs("NOPASSWD: ", stdout);
|
||||
else if (cm_list[i].nopasswd == FALSE && pwdef == TRUE)
|
||||
else if (cm_list[i].nopasswd == FALSE && !sudo_flag_set(FL_AUTHENTICATE))
|
||||
(void) fputs("PASSWD: ", stdout);
|
||||
|
||||
/* Print the actual command or expanded Cmnd_Alias. */
|
||||
|
188
sudo.c
188
sudo.c
@@ -75,6 +75,7 @@
|
||||
|
||||
#include "sudo.h"
|
||||
#include "interfaces.h"
|
||||
#include "version.h"
|
||||
|
||||
#ifndef STDC_HEADERS
|
||||
extern char *getenv __P((char *));
|
||||
@@ -182,15 +183,6 @@ main(argc, argv)
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Initialize syslog(3) if we are using it. */
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
# ifdef LOG_NFACILITIES
|
||||
openlog("sudo", 0, LOGFAC);
|
||||
# else
|
||||
openlog("sudo", 0);
|
||||
# endif /* LOG_NFACILITIES */
|
||||
#endif /* LOGGING & SLOG_SYSLOG */
|
||||
|
||||
/* Catch children as they die... */
|
||||
#ifdef POSIX_SIGNALS
|
||||
(void) memset((VOID *)&sa, 0, sizeof(sa));
|
||||
@@ -228,18 +220,34 @@ main(argc, argv)
|
||||
/*
|
||||
* Set the prompt based on $SUDO_PROMPT (can be overridden by `-p')
|
||||
*/
|
||||
if ((user_prompt = getenv("SUDO_PROMPT")) == NULL)
|
||||
user_prompt = PASSPROMPT;
|
||||
user_prompt = getenv("SUDO_PROMPT");
|
||||
|
||||
/* Parse our arguments. */
|
||||
sudo_mode = parse_args();
|
||||
|
||||
/* Setup defaults data structures. */
|
||||
init_defaults();
|
||||
|
||||
/* Initialize syslog(3) if we are using it. */
|
||||
if (sudo_inttable[I_LOGFAC] != (unsigned int)-1) {
|
||||
#ifdef LOG_NFACILITIES
|
||||
openlog("sudo", 0, sudo_inttable[I_LOGFAC]);
|
||||
#else
|
||||
openlog("sudo", 0);
|
||||
#endif /* LOG_NFACILITIES */
|
||||
}
|
||||
|
||||
if (sudo_mode & MODE_SHELL)
|
||||
user_cmnd = "shell";
|
||||
else
|
||||
switch (sudo_mode) {
|
||||
case MODE_VERSION:
|
||||
print_version();
|
||||
(void) printf("Sudo version %s\n", version);
|
||||
if (getuid() == 0) {
|
||||
putchar('\n');
|
||||
dump_auth_methods();
|
||||
dump_defaults();
|
||||
}
|
||||
exit(0);
|
||||
break;
|
||||
case MODE_HELP:
|
||||
@@ -252,6 +260,10 @@ main(argc, argv)
|
||||
case MODE_INVALIDATE:
|
||||
user_cmnd = "kill";
|
||||
break;
|
||||
case MODE_LISTDEFS:
|
||||
list_options();
|
||||
exit(0);
|
||||
break;
|
||||
case MODE_LIST:
|
||||
user_cmnd = "list";
|
||||
printmatches = 1;
|
||||
@@ -281,14 +293,22 @@ main(argc, argv)
|
||||
validated =
|
||||
sudoers_lookup((sudo_mode != MODE_VALIDATE && sudo_mode != MODE_LIST));
|
||||
|
||||
if (validated & VALIDATE_ERROR)
|
||||
log_error(0, "parse error in %s near line %d", _PATH_SUDOERS,
|
||||
errorlineno);
|
||||
|
||||
/* Is root even allowed to run sudo? */
|
||||
if (getuid() == 0 && !sudo_flag_set(FL_ROOT_SUDO)) {
|
||||
(void) fputs("You are already root, you don't need to use sudo.\n",
|
||||
stderr);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Require a password unless the NOPASS tag was set. */
|
||||
if (!(validated & FLAG_NOPASS))
|
||||
check_user();
|
||||
|
||||
if (validated & VALIDATE_ERROR)
|
||||
log_error(0, "parse error in %s near line %d", _PATH_SUDOERS,
|
||||
errorlineno);
|
||||
else if (validated & VALIDATE_OK) {
|
||||
if (validated & VALIDATE_OK) {
|
||||
/* Finally tell the user if the command did not exist. */
|
||||
if (cmnd_status == NOT_FOUND_DOT) {
|
||||
(void) fprintf(stderr, "%s: ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.\n", Argv[0], user_cmnd, user_cmnd, user_cmnd);
|
||||
@@ -322,9 +342,8 @@ main(argc, argv)
|
||||
"please report this error to sudo-bugs@courtesan.com");
|
||||
}
|
||||
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
closelog();
|
||||
#endif
|
||||
if (sudo_inttable[I_LOGFAC] != (unsigned int)-1)
|
||||
closelog();
|
||||
|
||||
/* Reset signal mask before we exec. */
|
||||
#ifdef POSIX_SIGNALS
|
||||
@@ -333,6 +352,18 @@ main(argc, argv)
|
||||
(void) sigsetmask(omask);
|
||||
#endif /* POSIX_SIGNALS */
|
||||
|
||||
/* Override user's umask if configured to do so. */
|
||||
if (sudo_inttable[I_UMASK] != 0777)
|
||||
(void) umask((mode_t)sudo_inttable[I_UMASK]);
|
||||
|
||||
/* Replace the PATH envariable with a secure one. */
|
||||
if (sudo_strtable[I_SECURE_PATH] && !user_is_exempt())
|
||||
if (sudo_setenv("PATH", sudo_strtable[I_SECURE_PATH])) {
|
||||
(void) fprintf(stderr, "%s: cannot allocate memory!\n",
|
||||
Argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
#ifndef PROFILING
|
||||
if ((sudo_mode & MODE_BACKGROUND) && fork() > 0)
|
||||
exit(0);
|
||||
@@ -351,24 +382,25 @@ main(argc, argv)
|
||||
log_auth(validated, 1);
|
||||
exit(1);
|
||||
} else if (validated & VALIDATE_NOT_OK) {
|
||||
#ifndef DONT_LEAK_PATH_INFO
|
||||
/*
|
||||
* We'd like to not leak path info at all here, but that can
|
||||
* *really* confuse the users. To really close the leak we'd
|
||||
* have to say "not allowed to run foo" even when the problem
|
||||
* is just "no foo in path" since the user can trivially set
|
||||
* their path to just contain a single dir.
|
||||
*/
|
||||
log_auth(validated,
|
||||
!(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
|
||||
if (cmnd_status == NOT_FOUND)
|
||||
(void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
|
||||
user_cmnd);
|
||||
else if (cmnd_status == NOT_FOUND_DOT)
|
||||
(void) fprintf(stderr, "%s: ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.\n", Argv[0], user_cmnd, user_cmnd, user_cmnd);
|
||||
#else
|
||||
log_auth(validated, 1);
|
||||
#endif /* DONT_LEAK_PATH_INFO */
|
||||
if (sudo_flag_set(FL_PATH_INFO)) {
|
||||
/*
|
||||
* We'd like to not leak path info at all here, but that can
|
||||
* *really* confuse the users. To really close the leak we'd
|
||||
* have to say "not allowed to run foo" even when the problem
|
||||
* is just "no foo in path" since the user can trivially set
|
||||
* their path to just contain a single dir.
|
||||
*/
|
||||
log_auth(validated,
|
||||
!(cmnd_status == NOT_FOUND_DOT || cmnd_status == NOT_FOUND));
|
||||
if (cmnd_status == NOT_FOUND)
|
||||
(void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
|
||||
user_cmnd);
|
||||
else if (cmnd_status == NOT_FOUND_DOT)
|
||||
(void) fprintf(stderr, "%s: ignoring `%s' found in '.'\nUse `sudo ./%s' if this is the `%s' you wish to run.\n", Argv[0], user_cmnd, user_cmnd, user_cmnd);
|
||||
} else {
|
||||
/* Just tell the user they are not allowed to run foo. */
|
||||
log_auth(validated, 1);
|
||||
}
|
||||
exit(1);
|
||||
} else {
|
||||
/* should never get here */
|
||||
@@ -387,17 +419,7 @@ init_vars(sudo_mode)
|
||||
int sudo_mode;
|
||||
{
|
||||
char *p, thost[MAXHOSTNAMELEN];
|
||||
#ifdef FQDN
|
||||
struct hostent *hp;
|
||||
#endif /* FQDN */
|
||||
|
||||
#ifdef NO_ROOT_SUDO
|
||||
if (getuid() == 0) {
|
||||
(void) fputs("You are already root, you don't need to use sudo.\n",
|
||||
stderr);
|
||||
exit(1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Sanity check command from user. */
|
||||
if (user_cmnd == NULL && strlen(NewArgv[0]) >= MAXPATHLEN) {
|
||||
@@ -410,21 +432,7 @@ init_vars(sudo_mode)
|
||||
(void) tzset(); /* set the timezone if applicable */
|
||||
#endif /* HAVE_TZSET */
|
||||
|
||||
#ifdef SECURE_PATH
|
||||
/* Replace the PATH envariable with a secure one. */
|
||||
if (!user_is_exempt() && sudo_setenv("PATH", SECURE_PATH)) {
|
||||
(void) fprintf(stderr, "%s: cannot allocate memory!\n", Argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
#endif /* SECURE_PATH */
|
||||
|
||||
#ifdef SUDO_UMASK
|
||||
(void) umask((mode_t)SUDO_UMASK);
|
||||
#endif /* SUDO_UMASK */
|
||||
|
||||
/* Default values for runas and cmnd, overridden later. */
|
||||
if (user_runas == NULL)
|
||||
user_runas = RUNAS_DEFAULT;
|
||||
/* Default value for cmnd and cwd, overridden later. */
|
||||
if (user_cmnd == NULL)
|
||||
user_cmnd = NewArgv[0];
|
||||
(void) strcpy(user_cwd, "unknown");
|
||||
@@ -440,13 +448,15 @@ init_vars(sudo_mode)
|
||||
log_error(USE_ERRNO|MSG_ONLY, "can't get hostname");
|
||||
} else
|
||||
user_host = estrdup(thost);
|
||||
#ifdef FQDN
|
||||
if (!(hp = gethostbyname(user_host)))
|
||||
log_error(USE_ERRNO|MSG_ONLY|NO_EXIT,
|
||||
"unable to lookup %s via gethostbyname()", user_host);
|
||||
else
|
||||
user_host = estrdup(hp->h_name);
|
||||
#endif /* FQDN */
|
||||
if (sudo_flag_set(FL_FQDN)) {
|
||||
if (!(hp = gethostbyname(user_host))) {
|
||||
log_error(USE_ERRNO|MSG_ONLY|NO_EXIT,
|
||||
"unable to lookup %s via gethostbyname()", user_host);
|
||||
} else {
|
||||
free(user_host);
|
||||
user_host = estrdup(hp->h_name);
|
||||
}
|
||||
}
|
||||
if ((p = strchr(user_host, '.'))) {
|
||||
*p = '\0';
|
||||
user_shost = estrdup(user_host);
|
||||
@@ -545,15 +555,12 @@ parse_args()
|
||||
NewArgv = Argv + 1;
|
||||
NewArgc = Argc - 1;
|
||||
|
||||
#ifdef SHELL_IF_NO_ARGS
|
||||
if (Argc < 2) { /* no options and no command */
|
||||
if (!sudo_flag_set(FL_SHELL_NOARGS))
|
||||
usage(1);
|
||||
rval |= MODE_SHELL;
|
||||
return(rval);
|
||||
}
|
||||
#else
|
||||
if (Argc < 2) /* no options and no command */
|
||||
usage(1);
|
||||
#endif /* SHELL_IF_NO_ARGS */
|
||||
|
||||
while (NewArgc > 0 && NewArgv[0][0] == '-') {
|
||||
if (NewArgv[0][1] != '\0' && NewArgv[0][2] != '\0') {
|
||||
@@ -592,7 +599,7 @@ parse_args()
|
||||
if (NewArgv[1] == NULL)
|
||||
usage(1);
|
||||
|
||||
user_runas = NewArgv[1];
|
||||
user_runas = &NewArgv[1];
|
||||
|
||||
/* Shift Argv over and adjust Argc. */
|
||||
NewArgc--;
|
||||
@@ -619,6 +626,12 @@ parse_args()
|
||||
usage_excl(1);
|
||||
excl = 'K';
|
||||
break;
|
||||
case 'L':
|
||||
rval = MODE_LISTDEFS;
|
||||
if (excl && excl != 'L')
|
||||
usage_excl(1);
|
||||
excl = 'L';
|
||||
break;
|
||||
case 'l':
|
||||
rval = MODE_LIST;
|
||||
if (excl && excl != 'l')
|
||||
@@ -639,9 +652,8 @@ parse_args()
|
||||
break;
|
||||
case 's':
|
||||
rval |= MODE_SHELL;
|
||||
#ifdef SHELL_SETS_HOME
|
||||
rval |= MODE_RESET_HOME;
|
||||
#endif /* SHELL_SETS_HOME */
|
||||
if (sudo_flag_set(FL_SET_HOME))
|
||||
rval |= MODE_RESET_HOME;
|
||||
break;
|
||||
case 'H':
|
||||
rval |= MODE_RESET_HOME;
|
||||
@@ -649,10 +661,8 @@ parse_args()
|
||||
case '-':
|
||||
NewArgc--;
|
||||
NewArgv++;
|
||||
#ifdef SHELL_IF_NO_ARGS
|
||||
if (rval == MODE_RUN)
|
||||
if (sudo_flag_set(FL_SHELL_NOARGS) && rval == MODE_RUN)
|
||||
rval |= MODE_SHELL;
|
||||
#endif /* SHELL_IF_NO_ARGS */
|
||||
return(rval);
|
||||
case '\0':
|
||||
(void) fprintf(stderr, "%s: '-' requires an argument\n",
|
||||
@@ -913,18 +923,18 @@ set_perms(perm, sudo_mode)
|
||||
}
|
||||
|
||||
/* XXX - add group/gid support */
|
||||
if (*user_runas == '#') {
|
||||
if (setuid(atoi(user_runas + 1))) {
|
||||
if (**user_runas == '#') {
|
||||
if (setuid(atoi(*user_runas + 1))) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: cannot set uid to %s: %s\n",
|
||||
Argv[0], user_runas, strerror(errno));
|
||||
Argv[0], *user_runas, strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
if (!(pw = getpwnam(user_runas))) {
|
||||
if (!(pw = getpwnam(*user_runas))) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: no passwd entry for %s!\n",
|
||||
Argv[0], user_runas);
|
||||
Argv[0], *user_runas);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
@@ -954,8 +964,8 @@ set_perms(perm, sudo_mode)
|
||||
* Initialize group vector only if are
|
||||
* going to run as a non-root user.
|
||||
*/
|
||||
if (strcmp(user_runas, "root") != 0 &&
|
||||
initgroups(user_runas, pw->pw_gid)
|
||||
if (strcmp(*user_runas, "root") != 0 &&
|
||||
initgroups(*user_runas, pw->pw_gid)
|
||||
== -1) {
|
||||
(void) fprintf(stderr,
|
||||
"%s: cannot set group vector: %s\n",
|
||||
@@ -1029,7 +1039,7 @@ usage(exit_val)
|
||||
int exit_val;
|
||||
{
|
||||
(void) fprintf(stderr,
|
||||
"usage: %s -V | -h | -l | -v | -k | -K | -H | [-b] [-p prompt]\n%*s",
|
||||
"usage: %s -V | -h | -L | -l | -v | -k | -K | -H | [-b] [-p prompt]\n%*s",
|
||||
Argv[0], (int) strlen(Argv[0]) + 8, " ");
|
||||
#ifdef HAVE_KERB5
|
||||
(void) fprintf(stderr, "[-r realm] ");
|
||||
|
15
sudo.h
15
sudo.h
@@ -39,6 +39,7 @@
|
||||
|
||||
#include <pathnames.h>
|
||||
#include "compat.h"
|
||||
#include "defaults.h"
|
||||
#include "logging.h"
|
||||
|
||||
/*
|
||||
@@ -50,7 +51,7 @@ struct sudo_user {
|
||||
char cwd[MAXPATHLEN];
|
||||
char *host;
|
||||
char *shost;
|
||||
char *runas;
|
||||
char **runas;
|
||||
char *prompt;
|
||||
char *cmnd_safe;
|
||||
char *cmnd;
|
||||
@@ -95,9 +96,10 @@ struct sudo_user {
|
||||
#define MODE_VERSION 00020
|
||||
#define MODE_HELP 00040
|
||||
#define MODE_LIST 00100
|
||||
#define MODE_BACKGROUND 00200
|
||||
#define MODE_SHELL 00400
|
||||
#define MODE_RESET_HOME 01000
|
||||
#define MODE_LISTDEFS 00200
|
||||
#define MODE_BACKGROUND 00400
|
||||
#define MODE_SHELL 01000
|
||||
#define MODE_RESET_HOME 02000
|
||||
|
||||
/*
|
||||
* Used with set_perms()
|
||||
@@ -173,7 +175,7 @@ int sudo_setenv __P((char *, char *));
|
||||
char *tgetpass __P((const char *, int, int));
|
||||
int find_path __P((char *, char **));
|
||||
void check_user __P((void));
|
||||
void verify_user __P((void));
|
||||
void verify_user __P((char *));
|
||||
int sudoers_lookup __P((int));
|
||||
void set_perms __P((int, int));
|
||||
void remove_timestamp __P((int));
|
||||
@@ -187,7 +189,8 @@ VOID *erealloc __P((VOID *, size_t));
|
||||
char *estrdup __P((const char *));
|
||||
void easprintf __P((char **, const char *, ...));
|
||||
void evasprintf __P((char **, const char *, va_list));
|
||||
void print_version __P((void));
|
||||
void dump_defaults __P((void));
|
||||
void dump_auth_methods __P((void));
|
||||
int lock_file __P((int, int));
|
||||
int touch __P((char *, time_t));
|
||||
YY_DECL;
|
||||
|
722
sudo.tab.c
722
sudo.tab.c
File diff suppressed because it is too large
Load Diff
25
sudo.tab.h
25
sudo.tab.h
@@ -4,17 +4,20 @@
|
||||
#define FQHOST 260
|
||||
#define NETGROUP 261
|
||||
#define USERGROUP 262
|
||||
#define NAME 263
|
||||
#define RUNAS 264
|
||||
#define NOPASSWD 265
|
||||
#define PASSWD 266
|
||||
#define ALL 267
|
||||
#define COMMENT 268
|
||||
#define HOSTALIAS 269
|
||||
#define CMNDALIAS 270
|
||||
#define USERALIAS 271
|
||||
#define RUNASALIAS 272
|
||||
#define ERROR 273
|
||||
#define WORD 263
|
||||
#define DEFAULTS 264
|
||||
#define DEFAULTS_HOST 265
|
||||
#define DEFAULTS_USER 266
|
||||
#define RUNAS 267
|
||||
#define NOPASSWD 268
|
||||
#define PASSWD 269
|
||||
#define ALL 270
|
||||
#define COMMENT 271
|
||||
#define HOSTALIAS 272
|
||||
#define CMNDALIAS 273
|
||||
#define USERALIAS 274
|
||||
#define RUNASALIAS 275
|
||||
#define ERROR 276
|
||||
typedef union {
|
||||
char *string;
|
||||
int BOOLEAN;
|
||||
|
@@ -296,9 +296,8 @@ main(argc, argv)
|
||||
Argv = argv;
|
||||
Argc = argc;
|
||||
|
||||
user_runas = RUNAS_DEFAULT;
|
||||
if (Argc >= 6 && strcmp(Argv[1], "-u") == 0) {
|
||||
user_runas = Argv[2];
|
||||
user_runas = &Argv[2];
|
||||
pw.pw_name = Argv[3];
|
||||
user_host = Argv[4];
|
||||
user_cmnd = Argv[5];
|
||||
@@ -343,6 +342,9 @@ main(argc, argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize default values. */
|
||||
init_defaults();
|
||||
|
||||
/* Warn about aliases that are used before being defined. */
|
||||
pedantic = TRUE;
|
||||
|
||||
@@ -368,7 +370,7 @@ main(argc, argv)
|
||||
(void) printf("cmnd_match : %d\n", cmnd_matches);
|
||||
(void) printf("no_passwd : %d\n", no_passwd);
|
||||
(void) printf("runas_match: %d\n", runas_matches);
|
||||
(void) printf("runas : %s\n", user_runas);
|
||||
(void) printf("runas : %s\n", *user_runas);
|
||||
top--;
|
||||
}
|
||||
}
|
||||
|
245
version.c
245
version.c
@@ -1,245 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1996, 1998, 1999 Todd C. Miller <Todd.Miller@courtesan.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. The name of the author may not be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
* 4. Products derived from this software may not be called "Sudo" nor
|
||||
* may "Sudo" appear in their names without specific prior written
|
||||
* permission from the author.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
|
||||
* THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
* OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
* OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#ifdef HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif /* HAVE_UNISTD_H */
|
||||
#ifdef HAVE_STRING_H
|
||||
#include <string.h>
|
||||
#endif /* HAVE_STRING_H */
|
||||
#ifdef HAVE_STRINGS_H
|
||||
#include <strings.h>
|
||||
#endif /* HAVE_STRINGS_H */
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
||||
#define SYSLOG_NAMES
|
||||
|
||||
#include "sudo.h"
|
||||
#include "version.h"
|
||||
#include "auth/sudo_auth.h"
|
||||
|
||||
#ifndef lint
|
||||
static const char rcsid[] = "$Sudo$";
|
||||
#endif /* lint */
|
||||
|
||||
#if (LOGGING & SLOG_SYSLOG) && defined(HAVE_SYSLOG_NAMES)
|
||||
static char *num_to_name __P((int, CODE *));
|
||||
#endif /* SLOG_SYSLOG && HAVE_SYSLOG_NAMES */
|
||||
|
||||
/*
|
||||
* Print version and configure info.
|
||||
*/
|
||||
void
|
||||
print_version()
|
||||
{
|
||||
extern sudo_auth auth_switch[];
|
||||
sudo_auth *auth;
|
||||
|
||||
(void) printf("Sudo version %s\n", version);
|
||||
|
||||
/*
|
||||
* Print compile-time options if root.
|
||||
* At some point these will all be in a structure of some kind
|
||||
* to allow overriding the defaults from sudoers.
|
||||
* XXX - reorganize for readability.
|
||||
*/
|
||||
if (getuid() == 0) {
|
||||
(void) printf("\nSudoers file: %s, mode 0%o, uid %d, gid %d\n",
|
||||
_PATH_SUDOERS, SUDOERS_MODE, SUDOERS_UID, SUDOERS_GID);
|
||||
(void) printf("Sudoers temp file: %s\n", _PATH_SUDOERS_TMP);
|
||||
|
||||
#ifdef NO_AUTHENTICATION
|
||||
(void) puts("No Authentication required by default.\n");
|
||||
#endif
|
||||
|
||||
(void) fputs("Authentication methods:", stdout);
|
||||
for (auth = auth_switch; auth->name; auth++)
|
||||
(void) printf(" '%s'", auth->name);
|
||||
(void) putchar('\n');
|
||||
|
||||
(void) fputs("Logging:\n", stdout);
|
||||
#if (LOGGING & SLOG_SYSLOG)
|
||||
# ifdef HAVE_SYSLOG_NAMES
|
||||
printf(" syslog: facility '%s', failures to '%s', success to '%s'\n",
|
||||
num_to_name(LOGFAC, facilitynames),
|
||||
num_to_name(PRI_FAILURE, prioritynames),
|
||||
num_to_name(PRI_SUCCESS, prioritynames));
|
||||
# else
|
||||
printf(" syslog: facility #%d, failures to #%d, success to #%d\n",
|
||||
LOGFAC, PRI_FAILURE, PRI_SUCCESS);
|
||||
# endif /* HAVE_SYSLOG_NAMES */
|
||||
#endif /* SLOG_SYSLOG */
|
||||
#if (LOGGING & SLOG_FILE)
|
||||
(void) printf(" log file: %s", _PATH_SUDO_LOGFILE);
|
||||
# ifdef HOST_IN_LOG
|
||||
(void) fputs(", host in log", stdout);
|
||||
# endif
|
||||
# ifdef WRAP_LOG
|
||||
(void) printf(", lines wrap after %d characters", MAXLOGFILELEN);
|
||||
# endif
|
||||
(void) putchar('\n');
|
||||
#endif /* SLOG_FILE */
|
||||
|
||||
#ifdef USE_TTY_TICKETS
|
||||
(void) puts("Timestamp type: userdir/tty");
|
||||
#else
|
||||
(void) puts("Timestamp type: userdir");
|
||||
#endif
|
||||
|
||||
#if TIMEOUT
|
||||
(void) printf("Ticket file timeout: %d minutes\n", TIMEOUT);
|
||||
#endif
|
||||
|
||||
#ifdef USE_INSULTS
|
||||
(void) fputs("Insult types:", stdout);
|
||||
# ifdef CLASSIC_INSULTS
|
||||
(void) fputs(" classic", stdout);
|
||||
# endif
|
||||
# ifdef CSOPS_INSULTS
|
||||
(void) fputs(" CSOps", stdout);
|
||||
# endif
|
||||
# ifdef HAL_INSULTS
|
||||
(void) fputs(" hal", stdout);
|
||||
# endif
|
||||
# ifdef GOONS_INSULTS
|
||||
(void) fputs(" goons", stdout);
|
||||
# endif
|
||||
(void) putchar('\n');
|
||||
# else
|
||||
(void) printf("Incorrect password message: %s\n", INCORRECT_PASSWORD);
|
||||
#endif
|
||||
|
||||
#ifdef SUDO_UMASK
|
||||
(void) printf("Umask to enforce: 0%o\n", SUDO_UMASK);
|
||||
#endif
|
||||
|
||||
#if !defined(WITHOUT_PASSWD) && PASSWORD_TIMEOUT
|
||||
(void) printf("Password timeout: %d minutes\n", PASSWORD_TIMEOUT);
|
||||
#endif
|
||||
|
||||
(void) printf("Password attempts allowed: %d\n", TRIES_FOR_PASSWORD);
|
||||
|
||||
(void) printf("Default user to run commands as: %s\n", RUNAS_DEFAULT);
|
||||
|
||||
#ifdef FQDN
|
||||
(void) puts("Fully qualified hostnames required in sudoers");
|
||||
#endif
|
||||
|
||||
#ifdef NO_ROOT_SUDO
|
||||
(void) puts("Root may not run sudo");
|
||||
#endif
|
||||
|
||||
#ifdef EXEMPTGROUP
|
||||
(void) printf("Users in group %s are exempt from password and PATH requirements\n", EXEMPTGROUP);
|
||||
#endif
|
||||
|
||||
#ifdef ENV_EDITOR
|
||||
(void) printf("Default editor for visudo: %s\n", EDITOR);
|
||||
#else
|
||||
(void) printf("Editor for visudo: %s\n", EDITOR);
|
||||
#endif
|
||||
|
||||
#if defined(IGNORE_DOT_PATH) || defined(DONT_LEAK_PATH_INFO) || defined(SECURE_PATH)
|
||||
puts("$PATH options:");
|
||||
#ifdef SECURE_PATH
|
||||
(void) printf(" PATH override: %s\n", SECURE_PATH);
|
||||
#endif
|
||||
# ifdef IGNORE_DOT_PATH
|
||||
(void) puts(" ignore '.'");
|
||||
# endif
|
||||
# ifdef DONT_LEAK_PATH_INFO
|
||||
(void) puts(" no information leakage");
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifdef _PATH_SENDMAIL
|
||||
(void) printf("Mailer path: %s\n", _PATH_SENDMAIL);
|
||||
(void) printf("Send mail to: %s\n", ALERTMAIL);
|
||||
(void) printf("Mail subject: %s\n", MAILSUBJECT);
|
||||
(void) fputs("Send mail on: 'error'", stdout);
|
||||
# ifdef SEND_MAIL_WHEN_NO_USER
|
||||
(void) fputs(" 'unlisted user'", stdout);
|
||||
# endif
|
||||
# ifdef SEND_MAIL_WHEN_NO_HOST
|
||||
(void) fputs(" 'unlisted on host'", stdout);
|
||||
# endif
|
||||
# ifdef SEND_MAIL_WHEN_NOT_OK
|
||||
(void) fputs(" 'authentication failure'", stdout);
|
||||
# endif
|
||||
(void) putchar('\n');
|
||||
#endif
|
||||
|
||||
#ifdef SHELL_IF_NO_ARGS
|
||||
puts("When invoked with no arguments sudo will start a shell");
|
||||
#endif
|
||||
|
||||
#ifdef SHELL_SETS_HOME
|
||||
puts("Sudo will set $HOME to the homedir of the target user");
|
||||
#endif
|
||||
|
||||
(void) printf("Default password prompt: %s\n", PASSPROMPT);
|
||||
|
||||
(void) fputs("Lecture user the first time they run sudo? ", stdout);
|
||||
#ifndef NO_LECTURE
|
||||
(void) puts("yes");
|
||||
#else
|
||||
(void) puts("no");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if (LOGGING & SLOG_SYSLOG) && defined(HAVE_SYSLOG_NAMES)
|
||||
/*
|
||||
* Convert a syslog number to a name. At some point in the
|
||||
* future, sudo will have its own tables internally so syslog
|
||||
* can be configured at run time.
|
||||
*/
|
||||
static char *
|
||||
num_to_name(num, table)
|
||||
int num;
|
||||
CODE *table;
|
||||
{
|
||||
CODE *t;
|
||||
|
||||
for (t = table; t->c_name; t++)
|
||||
if (t->c_val == num)
|
||||
return(t->c_name);
|
||||
|
||||
return("unknown");
|
||||
}
|
||||
#endif /* SLOG_SYSLOG && HAVE_SYSLOG_NAMES */
|
2
visudo.c
2
visudo.c
@@ -150,7 +150,6 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
/* Mock up a fake sudo_user struct. */
|
||||
user_runas = RUNAS_DEFAULT;
|
||||
user_host = user_shost = user_cmnd = "";
|
||||
if ((sudo_user.pw = getpwuid(getuid())) == NULL) {
|
||||
(void) fprintf(stderr, "%s: Can't find you in the passwd database.\n",
|
||||
@@ -273,6 +272,7 @@ main(argc, argv)
|
||||
}
|
||||
|
||||
/* Clean slate for each parse */
|
||||
init_defaults();
|
||||
init_parser();
|
||||
|
||||
/* Parse the sudoers file */
|
||||
|
Reference in New Issue
Block a user