Annotation of src/usr.bin/sudo/find_path.c, Revision 1.11
1.1 millert 1: /*
1.9 millert 2: * Copyright (c) 1996, 1998-2005 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 millert 3: *
1.8 millert 4: * Permission to use, copy, modify, and distribute this software for any
5: * purpose with or without fee is hereby granted, provided that the above
6: * copyright notice and this permission notice appear in all copies.
7: *
8: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1.7 millert 15: *
16: * Sponsored in part by the Defense Advanced Research Projects
17: * Agency (DARPA) and Air Force Research Laboratory, Air Force
18: * Materiel Command, USAF, under agreement number F39502-99-1-0512.
1.1 millert 19: */
20:
1.9 millert 21: #include <config.h>
1.1 millert 22:
1.3 millert 23: #include <sys/types.h>
24: #include <sys/param.h>
25: #include <sys/stat.h>
1.1 millert 26: #include <stdio.h>
27: #ifdef STDC_HEADERS
1.3 millert 28: # include <stdlib.h>
29: # include <stddef.h>
30: #else
31: # ifdef HAVE_STDLIB_H
32: # include <stdlib.h>
33: # endif
1.1 millert 34: #endif /* STDC_HEADERS */
1.3 millert 35: #ifdef HAVE_STRING_H
36: # include <string.h>
37: #else
38: # ifdef HAVE_STRINGS_H
39: # include <strings.h>
40: # endif
41: #endif /* HAVE_STRING_H */
1.1 millert 42: #ifdef HAVE_UNISTD_H
1.3 millert 43: # include <unistd.h>
1.1 millert 44: #endif /* HAVE_UNISTD_H */
45:
46: #include "sudo.h"
47:
48: /*
49: * This function finds the full pathname for a command and
50: * stores it in a statically allocated array, filling in a pointer
51: * to the array. Returns FOUND if the command was found, NOT_FOUND
52: * if it was not found, or NOT_FOUND_DOT if it would have been found
53: * but it is in '.' and IGNORE_DOT is set.
54: */
55: int
1.8 millert 56: find_path(infile, outfile, sbp, path)
1.1 millert 57: char *infile; /* file to find */
58: char **outfile; /* result parameter */
1.8 millert 59: struct stat *sbp; /* stat result parameter */
1.3 millert 60: char *path; /* path to search */
1.1 millert 61: {
1.8 millert 62: static char command[PATH_MAX]; /* qualified filename */
1.1 millert 63: char *n; /* for traversing path */
64: char *origpath; /* so we can free path later */
65: char *result = NULL; /* result of path/file lookup */
66: int checkdot = 0; /* check current dir? */
1.5 millert 67: int len; /* length parameter */
1.1 millert 68:
1.8 millert 69: if (strlen(infile) >= PATH_MAX)
1.10 millert 70: errorx(1, "%s: File name too long", infile);
1.1 millert 71:
72: /*
73: * If we were given a fully qualified or relative path
74: * there is no need to look at $PATH.
75: */
76: if (strchr(infile, '/')) {
1.5 millert 77: strlcpy(command, infile, sizeof(command)); /* paranoia */
1.8 millert 78: if (sudo_goodpath(command, sbp)) {
1.1 millert 79: *outfile = command;
80: return(FOUND);
81: } else
82: return(NOT_FOUND);
83: }
84:
1.3 millert 85: /* Use PATH passed in unless SECURE_PATH is in effect. */
1.10 millert 86: if (def_secure_path && !user_is_exempt())
87: path = def_secure_path;
88: else if (path == NULL)
1.1 millert 89: return(NOT_FOUND);
90: path = estrdup(path);
91: origpath = path;
92:
93: do {
94: if ((n = strchr(path, ':')))
95: *n = '\0';
96:
97: /*
98: * Search current dir last if it is in PATH This will miss sneaky
1.8 millert 99: * things like using './' or './/'
1.1 millert 100: */
101: if (*path == '\0' || (*path == '.' && *(path + 1) == '\0')) {
102: checkdot = 1;
103: path = n + 1;
104: continue;
105: }
106:
107: /*
108: * Resolve the path and exit the loop if found.
109: */
1.5 millert 110: len = snprintf(command, sizeof(command), "%s/%s", path, infile);
1.6 millert 111: if (len <= 0 || len >= sizeof(command))
1.10 millert 112: errorx(1, "%s: File name too long", infile);
1.8 millert 113: if ((result = sudo_goodpath(command, sbp)))
1.1 millert 114: break;
115:
116: path = n + 1;
117:
118: } while (n);
1.9 millert 119: efree(origpath);
1.1 millert 120:
121: /*
122: * Check current dir if dot was in the PATH
123: */
124: if (!result && checkdot) {
1.8 millert 125: result = sudo_goodpath(infile, sbp);
126: if (result && def_ignore_dot)
1.1 millert 127: return(NOT_FOUND_DOT);
128: }
129:
130: if (result) {
131: *outfile = result;
132: return(FOUND);
133: } else
134: return(NOT_FOUND);
135: }