unless the "-u" option is used). This option effectively makes the
"-s" flag imply "-H".
+ --disable-path-info
+ Normally, sudo will tell the user when a command could not be found
+ in their $PATH. Some sites may wish to disable this as it could
+ be used to gather information on the location of executables that
+ the normal user does not have access to.
+
--disable-sia
Disable SIA support. This is the "Security Integration Architecture"
on Digital UNIX.
/* Define if you want to ignore '.' and '' in $PATH */
#undef IGNORE_DOT_PATH
+/* Define if you want "command not allowed" instead of "command not found" */
+#undef DONT_LEAK_PATH_INFO
+
/* Define SHORT_MESSAGE for a short lecture or NO_MESSAGE for none. */
#undef SHORT_MESSAGE
#undef NO_MESSAGE
esac
], AC_MSG_RESULT(no))
+AC_MSG_CHECKING(whether to disable 'command not found' messages)
+AC_ARG_ENABLE(path_info,
+[ --disable-path-info Print 'command not allowed' not 'command not found'],
+[ case "$enableval" in
+ yes) AC_MSG_RESULT(no)
+ ;;
+ no) AC_MSG_RESULT(yes)
+ AC_DEFINE(DONT_LEAK_PATH_INFO)
+ ;;
+ *) AC_MSG_RESULT(no)
+ echo "Ignoring unknown argument to --enable-path-info: $enableval"
+ ;;
+ esac
+], AC_MSG_RESULT(no))
+
dnl
dnl If we don't have egrep we can't do anything...
dnl
* find_path()
*
* this function finds the full pathname for a command and
- * stores it in a statically allocated array, returning a pointer
- * to the array.
+ * 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.
*/
-char * find_path(file)
- char *file; /* file to find */
+int find_path(infile, outfile)
+ char *infile; /* file to find */
+ char **outfile; /* result parameter */
{
static char command[MAXPATHLEN]; /* qualified filename */
register char *n; /* for traversing path */
char *path = NULL; /* contents of PATH env var */
char *origpath; /* so we can free path later */
char *result = NULL; /* result of path/file lookup */
-#ifndef IGNORE_DOT_PATH
int checkdot = 0; /* check current dir? */
-#endif /* IGNORE_DOT_PATH */
command[0] = '\0';
- if (strlen(file) >= MAXPATHLEN) {
+ if (strlen(infile) >= MAXPATHLEN) {
errno = ENAMETOOLONG;
- (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], file);
+ (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
exit(1);
}
* We really want to fall back if !sudo_goodpath() but then
* the error is "not found" -- this way we get the correct error.
*/
- if (strchr(file, '/')) {
- (void) strcpy(command, file);
+ if (strchr(infile, '/')) {
+ (void) strcpy(command, infile);
if (sudo_goodpath(command)) {
- return(command);
+ *outfile = command;
+ return(FOUND);
} else {
(void) fprintf(stderr, "%s: %s: ", Argv[0], command);
perror("");
* grab PATH out of environment and make a local copy
*/
if ((path = getenv("PATH")) == NULL)
- return(NULL);
+ return(NOT_FOUND);
if ((path = (char *) strdup(path)) == NULL) {
(void) fprintf(stderr, "%s: out of memory!\n", Argv[0]);
exit(1);
}
- origpath=path;
+ origpath = path;
/* XXX use strtok() */
do {
* things like using './' or './/'
*/
if (*path == '\0' || (*path == '.' && *(path + 1) == '\0')) {
-#ifndef IGNORE_DOT_PATH
checkdot = 1;
-#endif /* IGNORE_DOT_PATH */
path = n + 1;
continue;
}
/*
* resolve the path and exit the loop if found
*/
- if (strlen(path) + strlen(file) + 1 >= MAXPATHLEN) {
- (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], file);
+ if (strlen(path) + strlen(infile) + 1 >= MAXPATHLEN) {
+ (void) fprintf(stderr, "%s: path too long: %s\n", Argv[0], infile);
exit(1);
}
- (void) sprintf(command, "%s/%s", path, file);
+ (void) sprintf(command, "%s/%s", path, infile);
if ((result = sudo_goodpath(command)))
break;
path = n + 1;
} while (n);
+ (void) free(origpath);
-#ifndef IGNORE_DOT_PATH
/*
- * check current dir if dot was in the PATH
+ * Check current dir if dot was in the PATH
*/
- if (!result && checkdot)
- result = sudo_goodpath(file);
+ if (!result && checkdot) {
+ result = sudo_goodpath(infile);
+#ifdef IGNORE_DOT_PATH
+ if (result)
+ return(NOT_FOUND_DOT);
#endif /* IGNORE_DOT_PATH */
+ }
- (void) free(origpath);
-
- return(result);
+ if (result) {
+ *outfile = result;
+ return(FOUND);
+ } else
+ return(NOT_FOUND);
}
int argc;
char **argv;
{
- int rtn, found_cmnd;
+ int rtn, cmnd_status = FOUND;
int sudo_mode = MODE_RUN;
extern char ** environ;
#endif /* SECURE_PATH */
if ((sudo_mode & MODE_RUN)) {
- found_cmnd = load_cmnd(sudo_mode); /* load the cmnd global variable */
+ cmnd_status = load_cmnd(sudo_mode); /* load the cmnd global variable */
} else if (sudo_mode == MODE_KILL) {
remove_timestamp(); /* remove the timestamp ticket file */
exit(0);
add_env(!(sudo_mode & MODE_SHELL)); /* add in SUDO_* envariables */
- /* validate the user but don't search for "validate" */
+ /* validate the user but don't search for pseudo-commands */
rtn = validate((sudo_mode != MODE_VALIDATE && sudo_mode != MODE_LIST));
switch (rtn) {
case VALIDATE_OK:
- case VALIDATE_OK_NOPASS:
- if (rtn != VALIDATE_OK_NOPASS)
- check_user();
+ check_user();
+ /* fallthrough */
+ case VALIDATE_OK_NOPASS:
/* finally tell the user if the command did not exist */
- if ((sudo_mode & MODE_RUN) && !found_cmnd) {
+ if (cmnd_status != FOUND) {
(void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
cmnd);
exit(1);
exit(-1);
break;
+ case VALIDATE_NOT_OK:
+ check_user();
+
+#ifndef DONT_LEAK_PATH_INFO
+ 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], cmnd, cmnd);
+ else if (cmnd_status == NOT_FOUND)
+ (void) fprintf(stderr, "%s: %s: command not found\n", Argv[0],
+ cmnd);
+ log_error(rtn);
+ exit(1);
+ break;
+#endif /* DONT_LEAK_PATH_INFO */
+
default:
log_error(rtn);
- set_perms(PERM_FULL_USER, sudo_mode);
inform_user(rtn);
exit(1);
break;
static int load_cmnd(sudo_mode)
int sudo_mode;
{
+ int retval;
+
if (strlen(NewArgv[0]) >= MAXPATHLEN) {
errno = ENAMETOOLONG;
(void) fprintf(stderr, "%s: %s: Pathname too long\n", Argv[0],
/*
* Resolve the path
*/
- if ((cmnd = find_path(NewArgv[0])) == NULL) {
+ if ((retval = find_path(NewArgv[0], &cmnd)) != FOUND)
cmnd = NewArgv[0];
- return(0);
- } else
- return(1);
+ return(retval);
}
* Boolean values
*/
#undef TRUE
-#define TRUE 0x01
+#define TRUE 1
#undef FALSE
-#define FALSE 0x00
+#define FALSE 0
+
+/*
+ * find_path()/load_cmnd() return values
+ */
+#define FOUND 1
+#define NOT_FOUND 0
+#define NOT_FOUND_DOT -1
/*
* Various modes sudo can be in (based on arguments) in octal
char *sudo_goodpath __P((const char *));
int sudo_setenv __P((char *, char *));
char *tgetpass __P((char *, int));
-char * find_path __P((char *));
+int find_path __P((char *, char **));
void log_error __P((int));
void inform_user __P((int));
void check_user __P((void));