Return to iolog_path.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers |
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: }