Annotation of embedaddon/sudo/plugins/sudoers/iolog_path.c, revision 1.1.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>