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

    1: /*
    2:  * Copyright (c) 1996, 1998-2005, 2007-2011
    3:  *	Todd C. Miller <Todd.Miller@courtesan.com>
    4:  *
    5:  * Permission to use, copy, modify, and distribute this software for any
    6:  * purpose with or without fee is hereby granted, provided that the above
    7:  * copyright notice and this permission notice appear in all copies.
    8:  *
    9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
   10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
   11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
   12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
   13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
   14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
   15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
   16:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
   17:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
   18:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   19:  *
   20:  * Sponsored in part by the Defense Advanced Research Projects
   21:  * Agency (DARPA) and Air Force Research Laboratory, Air Force
   22:  * Materiel Command, USAF, under agreement number F39502-99-1-0512.
   23:  */
   24: 
   25: #include <config.h>
   26: 
   27: #include <sys/types.h>
   28: #include <sys/param.h>
   29: #include <stdio.h>
   30: #ifdef STDC_HEADERS
   31: # include <stdlib.h>
   32: # include <stddef.h>
   33: #else
   34: # ifdef HAVE_STDLIB_H
   35: #  include <stdlib.h>
   36: # endif
   37: #endif /* STDC_HEADERS */
   38: #ifdef HAVE_STRING_H
   39: # include <string.h>
   40: #endif /* HAVE_STRING_H */
   41: #ifdef HAVE_STRINGS_H
   42: # include <strings.h>
   43: #endif /* HAVE_STRINGS_H */
   44: #ifdef HAVE_UNISTD_H
   45: # include <unistd.h>
   46: #endif /* HAVE_UNISTD_H */
   47: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
   48: # include <malloc.h>
   49: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
   50: #include <ctype.h>
   51: #include "sudoers.h"
   52: #include "parse.h"
   53: #include "toke.h"
   54: #include <gram.h>
   55: 
   56: static int arg_len = 0;
   57: static int arg_size = 0;
   58: 
   59: static unsigned char
   60: hexchar(const char *s)
   61: {
   62:     int i;
   63:     int result = 0;
   64: 
   65:     s += 2; /* skip \\x */
   66:     for (i = 0; i < 2; i++) {
   67: 	switch (*s) {
   68: 	case 'A':
   69: 	case 'a':
   70: 	    result += 10;
   71: 	    break;
   72: 	case 'B':
   73: 	case 'b':
   74: 	    result += 11;
   75: 	    break;
   76: 	case 'C':
   77: 	case 'c':
   78: 	    result += 12;
   79: 	    break;
   80: 	case 'D':
   81: 	case 'd':
   82: 	    result += 13;
   83: 	    break;
   84: 	case 'E':
   85: 	case 'e':
   86: 	    result += 14;
   87: 	    break;
   88: 	case 'F':
   89: 	case 'f':
   90: 	    result += 15;
   91: 	    break;
   92: 	default:
   93: 	    result += *s - '0';
   94: 	    break;
   95: 	}
   96: 	if (i == 0) {
   97: 	    result *= 16;
   98: 	    s++;
   99: 	}
  100:     }
  101:     return (unsigned char)result;
  102: }
  103: 
  104: int
  105: fill_txt(const char *src, int len, int olen)
  106: {
  107:     char *dst;
  108: 
  109:     dst = olen ? realloc(yylval.string, olen + len + 1) : malloc(len + 1);
  110:     if (dst == NULL) {
  111: 	yyerror(_("unable to allocate memory"));
  112: 	return FALSE;
  113:     }
  114:     yylval.string = dst;
  115: 
  116:     /* Copy the string and collapse any escaped characters. */
  117:     dst += olen;
  118:     while (len--) {
  119: 	if (*src == '\\' && len) {
  120: 	    if (src[1] == 'x' && len >= 3 && 
  121: 		isxdigit((unsigned char) src[2]) &&
  122: 		isxdigit((unsigned char) src[3])) {
  123: 		*dst++ = hexchar(src);
  124: 		src += 4;
  125: 		len -= 3;
  126: 	    } else {
  127: 		src++;
  128: 		len--;
  129: 		*dst++ = *src++;
  130: 	    }
  131: 	} else {
  132: 	    *dst++ = *src++;
  133: 	}
  134:     }
  135:     *dst = '\0';
  136:     return TRUE;
  137: }
  138: 
  139: int
  140: append(const char *src, int len)
  141: {
  142:     int olen = 0;
  143: 
  144:     if (yylval.string != NULL)
  145: 	olen = strlen(yylval.string);
  146: 
  147:     return fill_txt(src, len, olen);
  148: }
  149: 
  150: #define SPECIAL(c) \
  151:     ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#')
  152: 
  153: int
  154: fill_cmnd(const char *src, int len)
  155: {
  156:     char *dst;
  157:     int i;
  158: 
  159:     arg_len = arg_size = 0;
  160: 
  161:     dst = yylval.command.cmnd = (char *) malloc(len + 1);
  162:     if (yylval.command.cmnd == NULL) {
  163: 	yyerror(_("unable to allocate memory"));
  164: 	return FALSE;
  165:     }
  166: 
  167:     /* Copy the string and collapse any escaped sudo-specific characters. */
  168:     for (i = 0; i < len; i++) {
  169: 	if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1]))
  170: 	    *dst++ = src[++i];
  171: 	else
  172: 	    *dst++ = src[i];
  173:     }
  174:     *dst = '\0';
  175: 
  176:     yylval.command.args = NULL;
  177:     return TRUE;
  178: }
  179: 
  180: int
  181: fill_args(const char *s, int len, int addspace)
  182: {
  183:     int new_len;
  184:     char *p;
  185: 
  186:     if (yylval.command.args == NULL) {
  187: 	addspace = 0;
  188: 	new_len = len;
  189:     } else
  190: 	new_len = arg_len + len + addspace;
  191: 
  192:     if (new_len >= arg_size) {
  193: 	/* Allocate more space than we need for subsequent args */
  194: 	while (new_len >= (arg_size += COMMANDARGINC))
  195: 	    ;
  196: 
  197: 	p = yylval.command.args ?
  198: 	    (char *) realloc(yylval.command.args, arg_size) :
  199: 	    (char *) malloc(arg_size);
  200: 	if (p == NULL) {
  201: 	    efree(yylval.command.args);
  202: 	    yyerror(_("unable to allocate memory"));
  203: 	    return FALSE;
  204: 	} else
  205: 	    yylval.command.args = p;
  206:     }
  207: 
  208:     /* Efficiently append the arg (with a leading space if needed). */
  209:     p = yylval.command.args + arg_len;
  210:     if (addspace)
  211: 	*p++ = ' ';
  212:     if (strlcpy(p, s, arg_size - (p - yylval.command.args)) != len) {
  213: 	yyerror(_("fill_args: buffer overflow"));	/* paranoia */
  214: 	return FALSE;
  215:     }
  216:     arg_len = new_len;
  217:     return TRUE;
  218: }
  219: 
  220: /*
  221:  * Check to make sure an IPv6 address does not contain multiple instances
  222:  * of the string "::".  Assumes strlen(s) >= 1.
  223:  * Returns TRUE if address is valid else FALSE.
  224:  */
  225: int
  226: ipv6_valid(const char *s)
  227: {
  228:     int nmatch = 0;
  229: 
  230:     for (; *s != '\0'; s++) {
  231: 	if (s[0] == ':' && s[1] == ':') {
  232: 	    if (++nmatch > 1)
  233: 		break;
  234: 	}
  235: 	if (s[0] == '/')
  236: 	    nmatch = 0;			/* reset if we hit netmask */
  237:     }
  238: 
  239:     return nmatch <= 1;
  240: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>