1: /*
2: * Copyright (c) 1996, 1998-2005, 2007-2013
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 <stdio.h>
29: #ifdef STDC_HEADERS
30: # include <stdlib.h>
31: # include <stddef.h>
32: #else
33: # ifdef HAVE_STDLIB_H
34: # include <stdlib.h>
35: # endif
36: #endif /* STDC_HEADERS */
37: #ifdef HAVE_STRING_H
38: # include <string.h>
39: #endif /* HAVE_STRING_H */
40: #ifdef HAVE_STRINGS_H
41: # include <strings.h>
42: #endif /* HAVE_STRINGS_H */
43: #ifdef HAVE_UNISTD_H
44: # include <unistd.h>
45: #endif /* HAVE_UNISTD_H */
46: #if defined(HAVE_MALLOC_H) && !defined(STDC_HEADERS)
47: # include <malloc.h>
48: #endif /* HAVE_MALLOC_H && !STDC_HEADERS */
49: #include <ctype.h>
50: #include <errno.h>
51:
52: #include "sudoers.h"
53: #include "parse.h"
54: #include "toke.h"
55: #include <gram.h>
56:
57: static int arg_len = 0;
58: static int arg_size = 0;
59:
60: bool
61: fill_txt(const char *src, int len, int olen)
62: {
63: char *dst;
64: debug_decl(fill_txt, SUDO_DEBUG_PARSER)
65:
66: dst = olen ? realloc(sudoerslval.string, olen + len + 1) : malloc(len + 1);
67: if (dst == NULL) {
68: warning(NULL);
69: sudoerserror(NULL);
70: debug_return_bool(false);
71: }
72: sudoerslval.string = dst;
73:
74: /* Copy the string and collapse any escaped characters. */
75: dst += olen;
76: while (len--) {
77: if (*src == '\\' && len) {
78: if (src[1] == 'x' && len >= 3 &&
79: isxdigit((unsigned char) src[2]) &&
80: isxdigit((unsigned char) src[3])) {
81: *dst++ = hexchar(src + 2);
82: src += 4;
83: len -= 3;
84: } else {
85: src++;
86: len--;
87: *dst++ = *src++;
88: }
89: } else {
90: *dst++ = *src++;
91: }
92: }
93: *dst = '\0';
94: debug_return_bool(true);
95: }
96:
97: bool
98: append(const char *src, int len)
99: {
100: int olen = 0;
101: debug_decl(append, SUDO_DEBUG_PARSER)
102:
103: if (sudoerslval.string != NULL)
104: olen = strlen(sudoerslval.string);
105:
106: debug_return_bool(fill_txt(src, len, olen));
107: }
108:
109: #define SPECIAL(c) \
110: ((c) == ',' || (c) == ':' || (c) == '=' || (c) == ' ' || (c) == '\t' || (c) == '#')
111:
112: bool
113: fill_cmnd(const char *src, int len)
114: {
115: char *dst;
116: int i;
117: debug_decl(fill_cmnd, SUDO_DEBUG_PARSER)
118:
119: arg_len = arg_size = 0;
120:
121: dst = sudoerslval.command.cmnd = (char *) malloc(len + 1);
122: if (sudoerslval.command.cmnd == NULL) {
123: warning(NULL);
124: sudoerserror(NULL);
125: debug_return_bool(false);
126: }
127:
128: /* Copy the string and collapse any escaped sudo-specific characters. */
129: for (i = 0; i < len; i++) {
130: if (src[i] == '\\' && i != len - 1 && SPECIAL(src[i + 1]))
131: *dst++ = src[++i];
132: else
133: *dst++ = src[i];
134: }
135: *dst = '\0';
136:
137: sudoerslval.command.args = NULL;
138: debug_return_bool(true);
139: }
140:
141: bool
142: fill_args(const char *s, int len, int addspace)
143: {
144: int new_len;
145: char *p;
146: debug_decl(fill_args, SUDO_DEBUG_PARSER)
147:
148: if (sudoerslval.command.args == NULL) {
149: addspace = 0;
150: new_len = len;
151: } else
152: new_len = arg_len + len + addspace;
153:
154: if (new_len >= arg_size) {
155: /* Allocate more space than we need for subsequent args */
156: while (new_len >= (arg_size += COMMANDARGINC))
157: ;
158:
159: p = sudoerslval.command.args ?
160: (char *) realloc(sudoerslval.command.args, arg_size) :
161: (char *) malloc(arg_size);
162: if (p == NULL) {
163: efree(sudoerslval.command.args);
164: warning(NULL);
165: sudoerserror(NULL);
166: debug_return_bool(false);
167: } else
168: sudoerslval.command.args = p;
169: }
170:
171: /* Efficiently append the arg (with a leading space if needed). */
172: p = sudoerslval.command.args + arg_len;
173: if (addspace)
174: *p++ = ' ';
175: if (strlcpy(p, s, arg_size - (p - sudoerslval.command.args)) != len) {
176: warningx(_("fill_args: buffer overflow")); /* paranoia */
177: sudoerserror(NULL);
178: debug_return_bool(false);
179: }
180: arg_len = new_len;
181: debug_return_bool(true);
182: }
183:
184: /*
185: * Check to make sure an IPv6 address does not contain multiple instances
186: * of the string "::". Assumes strlen(s) >= 1.
187: * Returns true if address is valid else false.
188: */
189: bool
190: ipv6_valid(const char *s)
191: {
192: int nmatch = 0;
193: debug_decl(ipv6_valid, SUDO_DEBUG_PARSER)
194:
195: for (; *s != '\0'; s++) {
196: if (s[0] == ':' && s[1] == ':') {
197: if (++nmatch > 1)
198: break;
199: }
200: if (s[0] == '/')
201: nmatch = 0; /* reset if we hit netmask */
202: }
203:
204: debug_return_bool(nmatch <= 1);
205: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>