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>