Annotation of src/usr.bin/sudo/find_path.c, Revision 1.9
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 */
1.6 millert 45: #ifdef HAVE_ERR_H
46: # include <err.h>
47: #else
48: # include "emul/err.h"
49: #endif /* HAVE_ERR_H */
1.1 millert 50:
51: #include "sudo.h"
52:
53: #ifndef lint
1.9 ! millert 54: __unused static const char rcsid[] = "$Sudo: find_path.c,v 1.108.2.4 2007/06/12 01:43:01 millert Exp $";
1.1 millert 55: #endif /* lint */
56:
57: /*
58: * This function finds the full pathname for a command and
59: * stores it in a statically allocated array, filling in a pointer
60: * to the array. Returns FOUND if the command was found, NOT_FOUND
61: * if it was not found, or NOT_FOUND_DOT if it would have been found
62: * but it is in '.' and IGNORE_DOT is set.
63: */
64: int
1.8 millert 65: find_path(infile, outfile, sbp, path)
1.1 millert 66: char *infile; /* file to find */
67: char **outfile; /* result parameter */
1.8 millert 68: struct stat *sbp; /* stat result parameter */
1.3 millert 69: char *path; /* path to search */
1.1 millert 70: {
1.8 millert 71: static char command[PATH_MAX]; /* qualified filename */
1.1 millert 72: char *n; /* for traversing path */
73: char *origpath; /* so we can free path later */
74: char *result = NULL; /* result of path/file lookup */
75: int checkdot = 0; /* check current dir? */
1.5 millert 76: int len; /* length parameter */
1.1 millert 77:
1.8 millert 78: if (strlen(infile) >= PATH_MAX)
1.6 millert 79: errx(1, "%s: File name too long", infile);
1.1 millert 80:
81: /*
82: * If we were given a fully qualified or relative path
83: * there is no need to look at $PATH.
84: */
85: if (strchr(infile, '/')) {
1.5 millert 86: strlcpy(command, infile, sizeof(command)); /* paranoia */
1.8 millert 87: if (sudo_goodpath(command, sbp)) {
1.1 millert 88: *outfile = command;
89: return(FOUND);
90: } else
91: return(NOT_FOUND);
92: }
93:
1.3 millert 94: /* Use PATH passed in unless SECURE_PATH is in effect. */
95: #ifdef SECURE_PATH
96: if (!user_is_exempt())
97: path = SECURE_PATH;
98: #endif /* SECURE_PATH */
99: if (path == NULL)
1.1 millert 100: return(NOT_FOUND);
101: path = estrdup(path);
102: origpath = path;
103:
104: do {
105: if ((n = strchr(path, ':')))
106: *n = '\0';
107:
108: /*
109: * Search current dir last if it is in PATH This will miss sneaky
1.8 millert 110: * things like using './' or './/'
1.1 millert 111: */
112: if (*path == '\0' || (*path == '.' && *(path + 1) == '\0')) {
113: checkdot = 1;
114: path = n + 1;
115: continue;
116: }
117:
118: /*
119: * Resolve the path and exit the loop if found.
120: */
1.5 millert 121: len = snprintf(command, sizeof(command), "%s/%s", path, infile);
1.6 millert 122: if (len <= 0 || len >= sizeof(command))
123: errx(1, "%s: File name too long", infile);
1.8 millert 124: if ((result = sudo_goodpath(command, sbp)))
1.1 millert 125: break;
126:
127: path = n + 1;
128:
129: } while (n);
1.9 ! millert 130: efree(origpath);
1.1 millert 131:
132: /*
133: * Check current dir if dot was in the PATH
134: */
135: if (!result && checkdot) {
1.8 millert 136: result = sudo_goodpath(infile, sbp);
137: if (result && def_ignore_dot)
1.1 millert 138: return(NOT_FOUND_DOT);
139: }
140:
141: if (result) {
142: *outfile = result;
143: return(FOUND);
144: } else
145: return(NOT_FOUND);
146: }