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