1From ccd166b73eaae4dd1e1785c63ceb9b303568ed46 Mon Sep 17 00:00:00 2001
2From: Khem Raj <raj.khem@gmail.com>
3Date: Tue, 21 Mar 2017 11:30:49 -0700
4Subject: [PATCH] bundle own base64 encode/decode functions
5
6Not all libc implementations provide it.
7as an aside libresolv is no longer needed
8
9Signed-off-by: Khem Raj <raj.khem@gmail.com>
10---
11 Makefile |   4 +-
12 base64.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
13 netcat.c |   2 +
14 socks.c  |   3 +
15 4 files changed, 320 insertions(+), 2 deletions(-)
16 create mode 100644 base64.c
17
18Index: netcat-openbsd-1.105/Makefile
19===================================================================
20--- netcat-openbsd-1.105.orig/Makefile
21+++ netcat-openbsd-1.105/Makefile
22@@ -1,9 +1,9 @@
23 #       $OpenBSD: Makefile,v 1.6 2001/09/02 18:45:41 jakob Exp $
24
25 PROG=	nc
26-SRCS=	netcat.c atomicio.c socks.c
27+SRCS=	netcat.c atomicio.c socks.c base64.c
28
29-LIBS=  `pkg-config --libs libbsd` -lresolv
30+LIBS=  `pkg-config --libs libbsd`
31 OBJS=  $(SRCS:.c=.o)
32 CFLAGS=  -g -O2
33 LDFLAGS=  -Wl,--no-add-needed
34Index: netcat-openbsd-1.105/base64.c
35===================================================================
36--- /dev/null
37+++ netcat-openbsd-1.105/base64.c
38@@ -0,0 +1,313 @@
39+/*
40+ * Copyright (c) 1996-1999 by Internet Software Consortium.
41+ *
42+ * Permission to use, copy, modify, and distribute this software for any
43+ * purpose with or without fee is hereby granted, provided that the above
44+ * copyright notice and this permission notice appear in all copies.
45+ *
46+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
47+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
48+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
49+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
50+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
51+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
52+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
53+ * SOFTWARE.
54+ */
55+
56+/*
57+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
58+ *
59+ * International Business Machines, Inc. (hereinafter called IBM) grants
60+ * permission under its copyrights to use, copy, modify, and distribute this
61+ * Software with or without fee, provided that the above copyright notice and
62+ * all paragraphs of this notice appear in all copies, and that the name of IBM
63+ * not be used in connection with the marketing of any product incorporating
64+ * the Software or modifications thereof, without specific, written prior
65+ * permission.
66+ *
67+ * To the extent it has a right to do so, IBM grants an immunity from suit
68+ * under its patents, if any, for the use, sale or manufacture of products to
69+ * the extent that such products are used for performing Domain Name System
70+ * dynamic updates in TCP/IP networks by means of the Software.  No immunity is
71+ * granted for any product per se or for any other function of any product.
72+ *
73+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
74+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
75+ * PARTICULAR PURPOSE.  IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
76+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
77+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
78+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
79+ */
80+
81+#if !defined(LINT) && !defined(CODECENTER)
82+static const char rcsid[] = "$BINDId: base64.c,v 8.7 1999/10/13 16:39:33 vixie Exp $";
83+#endif /* not lint */
84+
85+#include <sys/types.h>
86+#include <sys/param.h>
87+#include <sys/socket.h>
88+
89+#include <netinet/in.h>
90+#include <arpa/inet.h>
91+#include <arpa/nameser.h>
92+
93+#include <ctype.h>
94+#include <resolv.h>
95+#include <stdio.h>
96+#include <stdlib.h>
97+#include <string.h>
98+
99+#define Assert(Cond) if (!(Cond)) abort()
100+
101+static const char Base64[] =
102+	"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
103+static const char Pad64 = '=';
104+
105+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
106+   The following encoding technique is taken from RFC 1521 by Borenstein
107+   and Freed.  It is reproduced here in a slightly edited form for
108+   convenience.
109+
110+   A 65-character subset of US-ASCII is used, enabling 6 bits to be
111+   represented per printable character. (The extra 65th character, "=",
112+   is used to signify a special processing function.)
113+
114+   The encoding process represents 24-bit groups of input bits as output
115+   strings of 4 encoded characters. Proceeding from left to right, a
116+   24-bit input group is formed by concatenating 3 8-bit input groups.
117+   These 24 bits are then treated as 4 concatenated 6-bit groups, each
118+   of which is translated into a single digit in the base64 alphabet.
119+
120+   Each 6-bit group is used as an index into an array of 64 printable
121+   characters. The character referenced by the index is placed in the
122+   output string.
123+
124+                         Table 1: The Base64 Alphabet
125+
126+      Value Encoding  Value Encoding  Value Encoding  Value Encoding
127+          0 A            17 R            34 i            51 z
128+          1 B            18 S            35 j            52 0
129+          2 C            19 T            36 k            53 1
130+          3 D            20 U            37 l            54 2
131+          4 E            21 V            38 m            55 3
132+          5 F            22 W            39 n            56 4
133+          6 G            23 X            40 o            57 5
134+          7 H            24 Y            41 p            58 6
135+          8 I            25 Z            42 q            59 7
136+          9 J            26 a            43 r            60 8
137+         10 K            27 b            44 s            61 9
138+         11 L            28 c            45 t            62 +
139+         12 M            29 d            46 u            63 /
140+         13 N            30 e            47 v
141+         14 O            31 f            48 w         (pad) =
142+         15 P            32 g            49 x
143+         16 Q            33 h            50 y
144+
145+   Special processing is performed if fewer than 24 bits are available
146+   at the end of the data being encoded.  A full encoding quantum is
147+   always completed at the end of a quantity.  When fewer than 24 input
148+   bits are available in an input group, zero bits are added (on the
149+   right) to form an integral number of 6-bit groups.  Padding at the
150+   end of the data is performed using the '=' character.
151+
152+   Since all base64 input is an integral number of octets, only the
153+         -------------------------------------------------
154+   following cases can arise:
155+
156+       (1) the final quantum of encoding input is an integral
157+           multiple of 24 bits; here, the final unit of encoded
158+	   output will be an integral multiple of 4 characters
159+	   with no "=" padding,
160+       (2) the final quantum of encoding input is exactly 8 bits;
161+           here, the final unit of encoded output will be two
162+	   characters followed by two "=" padding characters, or
163+       (3) the final quantum of encoding input is exactly 16 bits;
164+           here, the final unit of encoded output will be three
165+	   characters followed by one "=" padding character.
166+   */
167+
168+int
169+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
170+	size_t datalength = 0;
171+	u_char input[3];
172+	u_char output[4];
173+	size_t i;
174+
175+	while (2 < srclength) {
176+		input[0] = *src++;
177+		input[1] = *src++;
178+		input[2] = *src++;
179+		srclength -= 3;
180+
181+		output[0] = input[0] >> 2;
182+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
183+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
184+		output[3] = input[2] & 0x3f;
185+		Assert(output[0] < 64);
186+		Assert(output[1] < 64);
187+		Assert(output[2] < 64);
188+		Assert(output[3] < 64);
189+
190+		if (datalength + 4 > targsize)
191+			return (-1);
192+		target[datalength++] = Base64[output[0]];
193+		target[datalength++] = Base64[output[1]];
194+		target[datalength++] = Base64[output[2]];
195+		target[datalength++] = Base64[output[3]];
196+	}
197+
198+	/* Now we worry about padding. */
199+	if (0 != srclength) {
200+		/* Get what's left. */
201+		input[0] = input[1] = input[2] = '\0';
202+		for (i = 0; i < srclength; i++)
203+			input[i] = *src++;
204+
205+		output[0] = input[0] >> 2;
206+		output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
207+		output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
208+		Assert(output[0] < 64);
209+		Assert(output[1] < 64);
210+		Assert(output[2] < 64);
211+
212+		if (datalength + 4 > targsize)
213+			return (-1);
214+		target[datalength++] = Base64[output[0]];
215+		target[datalength++] = Base64[output[1]];
216+		if (srclength == 1)
217+			target[datalength++] = Pad64;
218+		else
219+			target[datalength++] = Base64[output[2]];
220+		target[datalength++] = Pad64;
221+	}
222+	if (datalength >= targsize)
223+		return (-1);
224+	target[datalength] = '\0';	/* Returned value doesn't count \0. */
225+	return (datalength);
226+}
227+//libresolv_hidden_def (b64_ntop)
228+
229+/* skips all whitespace anywhere.
230+   converts characters, four at a time, starting at (or after)
231+   src from base - 64 numbers into three 8 bit bytes in the target area.
232+   it returns the number of data bytes stored at the target, or -1 on error.
233+ */
234+
235+int
236+b64_pton(char const *src, u_char *target, size_t targsize) {
237+	int tarindex, state, ch;
238+	char *pos;
239+
240+	state = 0;
241+	tarindex = 0;
242+
243+	while ((ch = *src++) != '\0') {
244+		if (isspace(ch))	/* Skip whitespace anywhere. */
245+			continue;
246+
247+		if (ch == Pad64)
248+			break;
249+
250+		pos = strchr(Base64, ch);
251+		if (pos == 0) 		/* A non-base64 character. */
252+			return (-1);
253+
254+		switch (state) {
255+		case 0:
256+			if (target) {
257+				if ((size_t)tarindex >= targsize)
258+					return (-1);
259+				target[tarindex] = (pos - Base64) << 2;
260+			}
261+			state = 1;
262+			break;
263+		case 1:
264+			if (target) {
265+				if ((size_t)tarindex + 1 >= targsize)
266+					return (-1);
267+				target[tarindex]   |=  (pos - Base64) >> 4;
268+				target[tarindex+1]  = ((pos - Base64) & 0x0f)
269+							<< 4 ;
270+			}
271+			tarindex++;
272+			state = 2;
273+			break;
274+		case 2:
275+			if (target) {
276+				if ((size_t)tarindex + 1 >= targsize)
277+					return (-1);
278+				target[tarindex]   |=  (pos - Base64) >> 2;
279+				target[tarindex+1]  = ((pos - Base64) & 0x03)
280+							<< 6;
281+			}
282+			tarindex++;
283+			state = 3;
284+			break;
285+		case 3:
286+			if (target) {
287+				if ((size_t)tarindex >= targsize)
288+					return (-1);
289+				target[tarindex] |= (pos - Base64);
290+			}
291+			tarindex++;
292+			state = 0;
293+			break;
294+		default:
295+			abort();
296+		}
297+	}
298+
299+	/*
300+	 * We are done decoding Base-64 chars.  Let's see if we ended
301+	 * on a byte boundary, and/or with erroneous trailing characters.
302+	 */
303+
304+	if (ch == Pad64) {		/* We got a pad char. */
305+		ch = *src++;		/* Skip it, get next. */
306+		switch (state) {
307+		case 0:		/* Invalid = in first position */
308+		case 1:		/* Invalid = in second position */
309+			return (-1);
310+
311+		case 2:		/* Valid, means one byte of info */
312+			/* Skip any number of spaces. */
313+			for ((void)NULL; ch != '\0'; ch = *src++)
314+				if (!isspace(ch))
315+					break;
316+			/* Make sure there is another trailing = sign. */
317+			if (ch != Pad64)
318+				return (-1);
319+			ch = *src++;		/* Skip the = */
320+			/* Fall through to "single trailing =" case. */
321+			/* FALLTHROUGH */
322+
323+		case 3:		/* Valid, means two bytes of info */
324+			/*
325+			 * We know this char is an =.  Is there anything but
326+			 * whitespace after it?
327+			 */
328+			for ((void)NULL; ch != '\0'; ch = *src++)
329+				if (!isspace(ch))
330+					return (-1);
331+
332+			/*
333+			 * Now make sure for cases 2 and 3 that the "extra"
334+			 * bits that slopped past the last full byte were
335+			 * zeros.  If we don't check them, they become a
336+			 * subliminal channel.
337+			 */
338+			if (target && target[tarindex] != 0)
339+				return (-1);
340+		}
341+	} else {
342+		/*
343+		 * We ended by seeing the end of the string.  Make sure we
344+		 * have no partial bytes lying around.
345+		 */
346+		if (state != 0)
347+			return (-1);
348+	}
349+
350+	return (tarindex);
351+}
352Index: netcat-openbsd-1.105/netcat.c
353===================================================================
354--- netcat-openbsd-1.105.orig/netcat.c
355+++ netcat-openbsd-1.105/netcat.c
356@@ -169,6 +169,9 @@ static int connect_with_timeout(int fd,
357         socklen_t salen, int ctimeout);
358 static void quit();
359
360+int	b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
361+int	b64_pton(char const *src, u_char *target, size_t targsize);
362+
363 int
364 main(int argc, char *argv[])
365 {
366Index: netcat-openbsd-1.105/socks.c
367===================================================================
368--- netcat-openbsd-1.105.orig/socks.c
369+++ netcat-openbsd-1.105/socks.c
370@@ -53,6 +53,9 @@
371 #define SOCKS_DOMAIN	3
372 #define SOCKS_IPV6	4
373
374+int	b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize);
375+int	b64_pton(char const *src, u_char *target, size_t targsize);
376+
377 int	remote_connect(const char *, const char *, struct addrinfo);
378 int	socks_connect(const char *, const char *, struct addrinfo,
379 	    const char *, const char *, struct addrinfo, int,
380