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