--- /dev/null
+/* $NetBSD: vis.c,v 1.44 2011/03/12 19:52:48 christos Exp $ */
+
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1999, 2005 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * HEAVILY trimmed down for use only in dhcpcd.
+ * Please use the source in NetBSD for a fuller working copy.
+ */
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "vis.h"
+
+#undef BELL
+#define BELL '\a'
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define iswhite(c) (c == ' ' || c == '\t' || c == '\n')
+
+/*
+ * This is do_vis, the central code of vis.
+ * dst: Pointer to the destination buffer
+ * c: Character to encode
+ * flag: Flag word
+ * nextc: The character following 'c'
+ * extra: Pointer to the list of extra characters to be
+ * backslash-protected.
+ */
+char *
+svis(char *dst, int c, int flag, int nextc, const char *extra)
+{
+ int isextra;
+
+ isextra = strchr(extra, c) != NULL;
+ if (!isextra && isascii(c) && (isgraph(c) || iswhite(c))) {
+ *dst++ = (char)c;
+ return dst;
+ }
+ if (flag & VIS_CSTYLE) {
+ switch (c) {
+ case '\n':
+ *dst++ = '\\'; *dst++ = 'n';
+ return dst;
+ case '\r':
+ *dst++ = '\\'; *dst++ = 'r';
+ return dst;
+ case '\b':
+ *dst++ = '\\'; *dst++ = 'b';
+ return dst;
+ case BELL:
+ *dst++ = '\\'; *dst++ = 'a';
+ return dst;
+ case '\v':
+ *dst++ = '\\'; *dst++ = 'v';
+ return dst;
+ case '\t':
+ *dst++ = '\\'; *dst++ = 't';
+ return dst;
+ case '\f':
+ *dst++ = '\\'; *dst++ = 'f';
+ return dst;
+ case ' ':
+ *dst++ = '\\'; *dst++ = 's';
+ return dst;
+ case '\0':
+ *dst++ = '\\'; *dst++ = '0';
+ if (isoctal(nextc)) {
+ *dst++ = '0';
+ *dst++ = '0';
+ }
+ return dst;
+ case '$': /* vis(1) - l */
+ break;
+ default:
+ if (isgraph(c)) {
+ *dst++ = '\\'; *dst++ = (char)c;
+ return dst;
+ }
+ }
+ }
+
+ *dst++ = '\\';
+ if (isextra || ((c & 0177) == ' ') || (flag & VIS_OCTAL)) {
+ *dst++ = (((unsigned char)c >> 6) & 03) + '0';
+ *dst++ = (((unsigned char)c >> 3) & 07) + '0';
+ *dst++ = ( (unsigned char)c & 07) + '0';
+ } else {
+ if (c & 0200) {
+ c &= 0177; *dst++ = 'M';
+ }
+
+ if (iscntrl(c)) {
+ *dst++ = '^';
+ if (c == 0177)
+ *dst++ = '?';
+ else
+ *dst++ = (char)c + '@';
+ } else {
+ *dst++ = '-'; *dst++ = (char)c;
+ }
+ }
+ return dst;
+}
#include <unistd.h>
#include "config.h"
+
+#ifdef HAVE_VIS_H
+#include <vis.h>
+#endif
+
#include "common.h"
#include "dhcp-common.h"
#include "dhcp.h"
return (ssize_t)count;
}
+/*
+ * Escape these characters to avoid any nastiness passing to a POSIX shell.
+ * See IEEE Std 1003.1, 2004 Shell Command Language, 2.2 Quoting
+ * space is not escaped.
+ */
+#define ESCAPE_CHARS "|&;<>()$`\\\"'\t\n"
+
+/*
+ * Prints a chunk of data to a string.
+ * Escapes some characters defnined above to try and avoid any loopholes
+ * in the shell we're passing to.
+ * Any non visible characters are escaped as an octal number.
+ */
ssize_t
print_string(char *s, size_t len, const uint8_t *data, size_t dl)
{
uint8_t c;
const uint8_t *e, *p;
- ssize_t bytes = 0;
- ssize_t r;
+ size_t bytes;
+ char v[5], *vp, *ve;
+ bytes = 0;
e = data + dl;
while (data < e) {
c = *data++;
if (p == e)
break;
}
- if (!isascii(c) || !isprint(c)) {
- if (s) {
- if (len < 5) {
- errno = ENOBUFS;
- return -1;
- }
- r = snprintf(s, len, "\\%03o", c);
- len -= (size_t)r;
- bytes += r;
- s += r;
- } else
- bytes += 4;
- continue;
- }
- switch (c) {
- case '"': /* FALLTHROUGH */
- case '\'': /* FALLTHROUGH */
- case '$': /* FALLTHROUGH */
- case '`': /* FALLTHROUGH */
- case '\\': /* FALLTHROUGH */
- case '|': /* FALLTHROUGH */
- case '&':
- if (s) {
- if (len < 3) {
- errno = ENOBUFS;
- return -1;
- }
- *s++ = '\\';
- len--;
- }
- bytes++;
- break;
+ ve = svis(v, c, VIS_CSTYLE | VIS_OCTAL,
+ data <= e ? *data : 0, ESCAPE_CHARS);
+ if (len < (size_t)(ve - v) + 1) {
+ errno = ENOBUFS;
+ return -1;
}
+ bytes += (size_t)(ve - v);
if (s) {
- *s++ = (char)c;
- len--;
+ vp = v;
+ while (vp != ve)
+ *s++ = *vp++;
}
- bytes++;
}
/* NULL */
if (s)
*s = '\0';
bytes++;
- return bytes;
+ return (ssize_t)bytes;
}
#define ADDRSZ 4
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
.\"
-.Dd September 15, 2014
+.Dd September 26, 2014
.Dt DHCPCD 8
.Os
.Sh NAME
for details on how these scripts work.
.Nm
currently ignores the exit code of the script.
+.Pp
+.Nm
+sanitises each variable passed from the DHCP/RA message by encoding non
+printable characters in escaped octal and escaping the following characters:
+.D1 | \*[Am] \&; \*[Lt] \*[Gt] \&( \&) $ ` \e \*q ' \
+\*[Lt]tab\*[Gt] \*[Lt]newline\*[Gt]
+.Pp
+It is possible to reverse this encoding by passing the variable to
+.Xr unvis 1 ,
+like so:
+.D1 printf \*q%s\*q \*qvariable_name\*q | unvis
.Ss Fine tuning
You can fine-tune the behaviour of
.Nm
so that
.Nm
knows which process to signal.
+.Pp
+.Nm
+sanitises variables using the
+.Xr svis 3
+function with the
+.Dv VIS_CTYPE
+and
+.Dv VIS_OCTAL
+flags which your libc may provide,
+or it's own compatible one if not.
+Some
+.Xr unvis 1
+implementations may not decode either correctly, depending on how they
+handle VIS_CTYPE in both
+.Xr vis 3
+and
+.Xr unvis 3 .
.Sh FILES
.Bl -ohang
.It Pa @SYSCONFDIR@/dhcpcd.conf