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