Annotation of embedaddon/sudo/plugins/sudoers/iolog_path.c, revision 1.1.1.5
1.1 misho 1: /*
1.1.1.4 misho 2: * Copyright (c) 2011-2013 Todd C. Miller <Todd.Miller@courtesan.com>
1.1 misho 3: *
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.
15: */
16:
17: #include <config.h>
18:
19: #include <sys/types.h>
20: #include <stdio.h>
21: #ifdef STDC_HEADERS
22: # include <stdlib.h>
23: # include <stddef.h>
24: #else
25: # ifdef HAVE_STDLIB_H
26: # include <stdlib.h>
27: # endif
28: #endif /* STDC_HEADERS */
29: #ifdef HAVE_STRING_H
30: # if defined(HAVE_MEMORY_H) && !defined(STDC_HEADERS)
31: # include <memory.h>
32: # endif
33: # include <string.h>
34: #endif /* HAVE_STRING_H */
35: #ifdef HAVE_STRINGS_H
36: # include <strings.h>
37: #endif /* HAVE_STRINGS_H */
38: #include <pwd.h>
39: #include <grp.h>
40: #include <time.h>
41:
42: #include "sudoers.h"
43:
44: struct path_escape {
45: const char *name;
1.1.1.3 misho 46: size_t (*copy_fn)(char *, size_t, char *);
1.1 misho 47: };
48:
49: static size_t
1.1.1.3 misho 50: fill_seq(char *str, size_t strsize, char *logdir)
1.1 misho 51: {
1.1.1.4 misho 52: #ifdef SUDOERS_NO_SEQ
53: debug_decl(fill_seq, SUDO_DEBUG_UTIL)
54: debug_return_size_t(strlcpy(str, "%{seq}", strsize));
55: #else
1.1 misho 56: static char sessid[7];
57: int len;
1.1.1.4 misho 58: debug_decl(fill_seq, SUDO_DEBUG_UTIL)
1.1 misho 59:
60: if (sessid[0] == '\0')
1.1.1.3 misho 61: io_nextid(logdir, def_iolog_dir, sessid);
1.1 misho 62:
63: /* Path is of the form /var/log/sudo-io/00/00/01. */
64: len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
65: sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
66: if (len < 0)
1.1.1.2 misho 67: debug_return_size_t(strsize); /* handle non-standard snprintf() */
68: debug_return_size_t(len);
1.1.1.4 misho 69: #endif /* SUDOERS_NO_SEQ */
1.1 misho 70: }
71:
72: static size_t
1.1.1.3 misho 73: fill_user(char *str, size_t strsize, char *unused)
1.1 misho 74: {
1.1.1.2 misho 75: debug_decl(fill_user, SUDO_DEBUG_UTIL)
76: debug_return_size_t(strlcpy(str, user_name, strsize));
1.1 misho 77: }
78:
79: static size_t
1.1.1.3 misho 80: fill_group(char *str, size_t strsize, char *unused)
1.1 misho 81: {
82: struct group *grp;
83: size_t len;
1.1.1.2 misho 84: debug_decl(fill_group, SUDO_DEBUG_UTIL)
1.1 misho 85:
86: if ((grp = sudo_getgrgid(user_gid)) != NULL) {
87: len = strlcpy(str, grp->gr_name, strsize);
1.1.1.3 misho 88: sudo_gr_delref(grp);
1.1 misho 89: } else {
90: len = strlen(str);
91: len = snprintf(str + len, strsize - len, "#%u",
92: (unsigned int) user_gid);
93: }
1.1.1.2 misho 94: debug_return_size_t(len);
1.1 misho 95: }
96:
97: static size_t
1.1.1.3 misho 98: fill_runas_user(char *str, size_t strsize, char *unused)
1.1 misho 99: {
1.1.1.2 misho 100: debug_decl(fill_runas_user, SUDO_DEBUG_UTIL)
101: debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
1.1 misho 102: }
103:
104: static size_t
1.1.1.3 misho 105: fill_runas_group(char *str, size_t strsize, char *unused)
1.1 misho 106: {
107: struct group *grp;
108: size_t len;
1.1.1.2 misho 109: debug_decl(fill_runas_group, SUDO_DEBUG_UTIL)
1.1 misho 110:
111: if (runas_gr != NULL) {
112: len = strlcpy(str, runas_gr->gr_name, strsize);
113: } else {
114: if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) {
115: len = strlcpy(str, grp->gr_name, strsize);
1.1.1.3 misho 116: sudo_gr_delref(grp);
1.1 misho 117: } else {
118: len = strlen(str);
119: len = snprintf(str + len, strsize - len, "#%u",
120: (unsigned int) runas_pw->pw_gid);
121: }
122: }
1.1.1.2 misho 123: debug_return_size_t(len);
1.1 misho 124: }
125:
126: static size_t
1.1.1.3 misho 127: fill_hostname(char *str, size_t strsize, char *unused)
1.1 misho 128: {
1.1.1.2 misho 129: debug_decl(fill_hostname, SUDO_DEBUG_UTIL)
130: debug_return_size_t(strlcpy(str, user_shost, strsize));
1.1 misho 131: }
132:
133: static size_t
1.1.1.3 misho 134: fill_command(char *str, size_t strsize, char *unused)
1.1 misho 135: {
1.1.1.2 misho 136: debug_decl(fill_command, SUDO_DEBUG_UTIL)
137: debug_return_size_t(strlcpy(str, user_base, strsize));
1.1 misho 138: }
139:
1.1.1.4 misho 140: /* Note: "seq" must be first in the list. */
141: static struct path_escape io_path_escapes[] = {
142: { "seq", fill_seq },
143: { "user", fill_user },
144: { "group", fill_group },
145: { "runas_user", fill_runas_user },
146: { "runas_group", fill_runas_group },
147: { "hostname", fill_hostname },
148: { "command", fill_command },
149: { NULL, NULL }
150: };
151:
1.1 misho 152: /*
153: * Concatenate dir + file, expanding any escape sequences.
154: * Returns the concatenated path and sets slashp point to
155: * the path separator between the expanded dir and file.
156: */
157: char *
158: expand_iolog_path(const char *prefix, const char *dir, const char *file,
159: char **slashp)
160: {
161: size_t len, prelen = 0;
162: char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX];
1.1.1.3 misho 163: char *slash = NULL;
1.1 misho 164: const char *endbrace, *src = dir;
1.1.1.4 misho 165: struct path_escape *escapes = NULL;
166: int pass, oldlocale;
1.1.1.2 misho 167: bool strfit;
168: debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL)
1.1 misho 169:
170: /* Expanded path must be <= PATH_MAX */
171: if (prefix != NULL)
172: prelen = strlen(prefix);
173: dst = path = emalloc(prelen + PATH_MAX);
174: *path = '\0';
175: pathend = path + prelen + PATH_MAX;
176:
177: /* Copy prefix, if present. */
178: if (prefix != NULL) {
179: memcpy(path, prefix, prelen);
180: dst += prelen;
181: *dst = '\0';
182: }
183:
184: /* Trim leading slashes from file component. */
185: while (*file == '/')
186: file++;
187:
188: for (pass = 0; pass < 3; pass++) {
1.1.1.2 misho 189: strfit = false;
1.1 misho 190: switch (pass) {
191: case 0:
192: src = dir;
1.1.1.4 misho 193: escapes = io_path_escapes + 1; /* skip "%{seq}" */
1.1 misho 194: break;
195: case 1:
196: /* Trim trailing slashes from dir component. */
197: while (dst - path - 1 > prelen && dst[-1] == '/')
198: dst--;
1.1.1.3 misho 199: /* The NUL will be replaced with a '/' at the end. */
200: if (dst + 1 >= pathend)
201: goto bad;
202: slash = dst++;
203: continue;
1.1 misho 204: case 2:
205: src = file;
1.1.1.3 misho 206: escapes = io_path_escapes;
1.1 misho 207: break;
208: }
209: dst0 = dst;
210: for (; *src != '\0'; src++) {
211: if (src[0] == '%') {
212: if (src[1] == '{') {
213: endbrace = strchr(src + 2, '}');
214: if (endbrace != NULL) {
215: struct path_escape *esc;
216: len = (size_t)(endbrace - src - 2);
217: for (esc = escapes; esc->name != NULL; esc++) {
218: if (strncmp(src + 2, esc->name, len) == 0 &&
219: esc->name[len] == '\0')
220: break;
221: }
222: if (esc->name != NULL) {
1.1.1.3 misho 223: len = esc->copy_fn(dst, (size_t)(pathend - dst),
224: path + prelen);
1.1 misho 225: if (len >= (size_t)(pathend - dst))
226: goto bad;
227: dst += len;
228: src = endbrace;
229: continue;
230: }
231: }
232: } else if (src[1] == '%') {
233: /* Collapse %% -> % */
234: src++;
235: } else {
236: /* May need strftime() */
237: strfit = 1;
238: }
239: }
240: /* Need at least 2 chars, including the NUL terminator. */
241: if (dst + 1 >= pathend)
242: goto bad;
243: *dst++ = *src;
244: }
245: *dst = '\0';
246:
247: /* Expand strftime escapes as needed. */
248: if (strfit) {
249: time_t now;
250: struct tm *timeptr;
251:
252: time(&now);
253: timeptr = localtime(&now);
254:
1.1.1.4 misho 255: /* Use sudoers locale for strftime() */
256: sudoers_setlocale(SUDOERS_LOCALE_SUDOERS, &oldlocale);
257:
1.1.1.5 ! misho 258: /* We only call strftime() on the current part of the buffer. */
1.1 misho 259: tmpbuf[sizeof(tmpbuf) - 1] = '\0';
260: len = strftime(tmpbuf, sizeof(tmpbuf), dst0, timeptr);
261:
1.1.1.4 misho 262: /* Restore old locale. */
263: sudoers_setlocale(oldlocale, NULL);
264:
1.1 misho 265: if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
266: goto bad; /* strftime() failed, buf too small? */
267:
268: if (len >= (size_t)(pathend - dst0))
269: goto bad; /* expanded buffer too big to fit. */
270: memcpy(dst0, tmpbuf, len);
271: dst = dst0 + len;
272: *dst = '\0';
273: }
274: }
1.1.1.3 misho 275: if (slashp)
276: *slashp = slash;
277: *slash = '/';
1.1 misho 278:
1.1.1.2 misho 279: debug_return_str(path);
1.1 misho 280: bad:
281: efree(path);
1.1.1.2 misho 282: debug_return_str(NULL);
1.1 misho 283: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>