Annotation of embedaddon/sudo/plugins/sudoers/iolog_path.c, revision 1.1.1.2
1.1 misho 1: /*
2: * Copyright (c) 2011 Todd C. Miller <Todd.Miller@courtesan.com>
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: #ifdef HAVE_SETLOCALE
39: # include <locale.h>
40: #endif
41: #include <pwd.h>
42: #include <grp.h>
43: #include <time.h>
44:
45: #include "sudoers.h"
46:
47: struct path_escape {
48: const char *name;
49: size_t (*copy_fn)(char *, size_t);
50: };
51:
52: static size_t fill_seq(char *, size_t);
53: static size_t fill_user(char *, size_t);
54: static size_t fill_group(char *, size_t);
55: static size_t fill_runas_user(char *, size_t);
56: static size_t fill_runas_group(char *, size_t);
57: static size_t fill_hostname(char *, size_t);
58: static size_t fill_command(char *, size_t);
59:
60: static struct path_escape escapes[] = {
61: { "seq", fill_seq },
62: { "user", fill_user },
63: { "group", fill_group },
64: { "runas_user", fill_runas_user },
65: { "runas_group", fill_runas_group },
66: { "hostname", fill_hostname },
67: { "command", fill_command },
68: { NULL, NULL }
69: };
70:
71: static size_t
72: fill_seq(char *str, size_t strsize)
73: {
74: static char sessid[7];
75: int len;
1.1.1.2 ! misho 76: debug_decl(sudoers_io_version, SUDO_DEBUG_UTIL)
1.1 misho 77:
78: if (sessid[0] == '\0')
79: io_nextid(def_iolog_dir, sessid);
80:
81: /* Path is of the form /var/log/sudo-io/00/00/01. */
82: len = snprintf(str, strsize, "%c%c/%c%c/%c%c", sessid[0],
83: sessid[1], sessid[2], sessid[3], sessid[4], sessid[5]);
84: if (len < 0)
1.1.1.2 ! misho 85: debug_return_size_t(strsize); /* handle non-standard snprintf() */
! 86: debug_return_size_t(len);
1.1 misho 87: }
88:
89: static size_t
90: fill_user(char *str, size_t strsize)
91: {
1.1.1.2 ! misho 92: debug_decl(fill_user, SUDO_DEBUG_UTIL)
! 93: debug_return_size_t(strlcpy(str, user_name, strsize));
1.1 misho 94: }
95:
96: static size_t
97: fill_group(char *str, size_t strsize)
98: {
99: struct group *grp;
100: size_t len;
1.1.1.2 ! misho 101: debug_decl(fill_group, SUDO_DEBUG_UTIL)
1.1 misho 102:
103: if ((grp = sudo_getgrgid(user_gid)) != NULL) {
104: len = strlcpy(str, grp->gr_name, strsize);
105: gr_delref(grp);
106: } else {
107: len = strlen(str);
108: len = snprintf(str + len, strsize - len, "#%u",
109: (unsigned int) user_gid);
110: }
1.1.1.2 ! misho 111: debug_return_size_t(len);
1.1 misho 112: }
113:
114: static size_t
115: fill_runas_user(char *str, size_t strsize)
116: {
1.1.1.2 ! misho 117: debug_decl(fill_runas_user, SUDO_DEBUG_UTIL)
! 118: debug_return_size_t(strlcpy(str, runas_pw->pw_name, strsize));
1.1 misho 119: }
120:
121: static size_t
122: fill_runas_group(char *str, size_t strsize)
123: {
124: struct group *grp;
125: size_t len;
1.1.1.2 ! misho 126: debug_decl(fill_runas_group, SUDO_DEBUG_UTIL)
1.1 misho 127:
128: if (runas_gr != NULL) {
129: len = strlcpy(str, runas_gr->gr_name, strsize);
130: } else {
131: if ((grp = sudo_getgrgid(runas_pw->pw_gid)) != NULL) {
132: len = strlcpy(str, grp->gr_name, strsize);
133: gr_delref(grp);
134: } else {
135: len = strlen(str);
136: len = snprintf(str + len, strsize - len, "#%u",
137: (unsigned int) runas_pw->pw_gid);
138: }
139: }
1.1.1.2 ! misho 140: debug_return_size_t(len);
1.1 misho 141: }
142:
143: static size_t
144: fill_hostname(char *str, size_t strsize)
145: {
1.1.1.2 ! misho 146: debug_decl(fill_hostname, SUDO_DEBUG_UTIL)
! 147: debug_return_size_t(strlcpy(str, user_shost, strsize));
1.1 misho 148: }
149:
150: static size_t
151: fill_command(char *str, size_t strsize)
152: {
1.1.1.2 ! misho 153: debug_decl(fill_command, SUDO_DEBUG_UTIL)
! 154: debug_return_size_t(strlcpy(str, user_base, strsize));
1.1 misho 155: }
156:
157: /*
158: * Concatenate dir + file, expanding any escape sequences.
159: * Returns the concatenated path and sets slashp point to
160: * the path separator between the expanded dir and file.
161: */
162: char *
163: expand_iolog_path(const char *prefix, const char *dir, const char *file,
164: char **slashp)
165: {
166: size_t len, prelen = 0;
167: char *dst, *dst0, *path, *pathend, tmpbuf[PATH_MAX];
168: const char *endbrace, *src = dir;
1.1.1.2 ! misho 169: int pass;
! 170: bool strfit;
! 171: debug_decl(expand_iolog_path, SUDO_DEBUG_UTIL)
1.1 misho 172:
173: /* Expanded path must be <= PATH_MAX */
174: if (prefix != NULL)
175: prelen = strlen(prefix);
176: dst = path = emalloc(prelen + PATH_MAX);
177: *path = '\0';
178: pathend = path + prelen + PATH_MAX;
179:
180: /* Copy prefix, if present. */
181: if (prefix != NULL) {
182: memcpy(path, prefix, prelen);
183: dst += prelen;
184: *dst = '\0';
185: }
186:
187: /* Trim leading slashes from file component. */
188: while (*file == '/')
189: file++;
190:
191: for (pass = 0; pass < 3; pass++) {
1.1.1.2 ! misho 192: strfit = false;
1.1 misho 193: switch (pass) {
194: case 0:
195: src = dir;
196: break;
197: case 1:
198: /* Trim trailing slashes from dir component. */
199: while (dst - path - 1 > prelen && dst[-1] == '/')
200: dst--;
201: if (slashp)
202: *slashp = dst;
203: src = "/";
204: break;
205: case 2:
206: src = file;
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) {
223: len = esc->copy_fn(dst, (size_t)(pathend - dst));
224: if (len >= (size_t)(pathend - dst))
225: goto bad;
226: dst += len;
227: src = endbrace;
228: continue;
229: }
230: }
231: } else if (src[1] == '%') {
232: /* Collapse %% -> % */
233: src++;
234: } else {
235: /* May need strftime() */
236: strfit = 1;
237: }
238: }
239: /* Need at least 2 chars, including the NUL terminator. */
240: if (dst + 1 >= pathend)
241: goto bad;
242: *dst++ = *src;
243: }
244: *dst = '\0';
245:
246: /* Expand strftime escapes as needed. */
247: if (strfit) {
248: time_t now;
249: struct tm *timeptr;
250:
251: time(&now);
252: timeptr = localtime(&now);
253:
254: #ifdef HAVE_SETLOCALE
255: if (!setlocale(LC_ALL, def_sudoers_locale)) {
256: warningx(_("unable to set locale to \"%s\", using \"C\""),
257: def_sudoers_locale);
258: setlocale(LC_ALL, "C");
259: }
260: #endif
261: /* We only calls strftime() on the current part of the buffer. */
262: tmpbuf[sizeof(tmpbuf) - 1] = '\0';
263: len = strftime(tmpbuf, sizeof(tmpbuf), dst0, timeptr);
264:
265: #ifdef HAVE_SETLOCALE
266: setlocale(LC_ALL, "");
267: #endif
268: if (len == 0 || tmpbuf[sizeof(tmpbuf) - 1] != '\0')
269: goto bad; /* strftime() failed, buf too small? */
270:
271: if (len >= (size_t)(pathend - dst0))
272: goto bad; /* expanded buffer too big to fit. */
273: memcpy(dst0, tmpbuf, len);
274: dst = dst0 + len;
275: *dst = '\0';
276: }
277: }
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>