File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / sudo / plugins / sudoers / iolog_path.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Feb 21 16:23:02 2012 UTC (12 years, 6 months ago) by misho
Branches: sudo, MAIN
CVS tags: v1_8_3p2, HEAD
sudo

    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>