Commit Diff


commit - 555b1b20f1dd665e730f3030b212a8f2352cd9e9
commit + c02557739cfc6b586c823fa8f9965e863a37e87c
blob - 7bfb74a6bb728afa3e1ccd6cc4b5202bef3e712f
blob + 3015ba6dc37054cfb7e638b7049f0732c6a2b873
--- Makefile
+++ Makefile
@@ -1,10 +1,10 @@
-#	$OpenBSD: Makefile,v 1.17 2008/02/11 10:42:50 reyk Exp $
+#	$OpenBSD: Makefile,v 1.18 2008/07/09 17:16:51 reyk Exp $
 
 PROG=		relayd
 SRCS=		parse.y log.c control.c buffer.c imsg.c ssl.c ssl_privsep.c \
 		relayd.c pfe.c pfe_filter.c hce.c relay.c relay_udp.c \
 		carp.c check_icmp.c check_tcp.c check_script.c name2id.c \
-		snmp.c
+		snmp.c shuffle.c
 MAN=		relayd.8 relayd.conf.5
 
 LDADD=		-levent -lssl -lcrypto
blob - 005ca6852c2e9b0a80e1b090d72cbea624dc407b
blob + c9432815bb0ca93ab4ba375e343969b9a3040a66
--- relay.c
+++ relay.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: relay.c,v 1.91 2008/07/09 14:57:01 reyk Exp $	*/
+/*	$OpenBSD: relay.c,v 1.92 2008/07/09 17:16:51 reyk Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -485,6 +485,16 @@ relay_init(void)
 			    rlay->rl_dstnhosts, rlay->rl_dsttable->conf.name,
 			    rlay->rl_dsttable->conf.check ? "" : " (no check)");
 		}
+
+		switch (rlay->rl_proto->type) {
+		case RELAY_PROTO_DNS:
+			relay_udp_init(rlay);
+			break;
+		case RELAY_PROTO_TCP:
+		case RELAY_PROTO_HTTP:
+			/* Use defaults */
+			break;
+		}
 	}
 
 	/* Schedule statistics timer */
blob - a2971a65f7a7290c21cb76583e6a2626b163956f
blob + 71fc4b87b09f3f750203f5b48f31ef492534eee8
--- relay_udp.c
+++ relay_udp.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: relay_udp.c,v 1.13 2008/07/09 14:57:01 reyk Exp $	*/
+/*	$OpenBSD: relay_udp.c,v 1.14 2008/07/09 17:16:51 reyk Exp $	*/
 
 /*
  * Copyright (c) 2007, 2008 Reyk Floeter <reyk@openbsd.org>
@@ -54,6 +54,7 @@ extern struct imsgbuf *ibuf_pfe;
 extern int debug;
 
 struct relayd *env = NULL;
+struct shuffle relay_shuffle;
 
 int		 relay_udp_socket(struct sockaddr_storage *, in_port_t,
 		    struct protocol *);
@@ -72,20 +73,25 @@ int		 relay_dns_cmp(struct session *, struct session *
 void
 relay_udp_privinit(struct relayd *x_env, struct relay *rlay)
 {
-	struct protocol		*proto = rlay->rl_proto;
-
 	if (env == NULL)
 		env = x_env;
 
 	if (rlay->rl_conf.flags & F_SSL)
 		fatalx("ssl over udp is not supported");
 	rlay->rl_conf.flags |= F_UDP;
+}
 
+void
+relay_udp_init(struct relay *rlay)
+{
+	struct protocol		*proto = rlay->rl_proto;
+
 	switch (proto->type) {
 	case RELAY_PROTO_DNS:
 		proto->validate = relay_dns_validate;
 		proto->request = relay_dns_request;
 		proto->cmp = relay_dns_cmp;
+		shuffle_init(&relay_shuffle);
 		break;
 	default:
 		fatalx("unsupported udp protocol");
@@ -401,7 +407,7 @@ relay_dns_validate(struct session *con, struct relay *
 		priv = malloc(sizeof(struct relay_dns_priv));
 		if (priv == NULL)
 			return (NULL);
-		priv->dp_inkey = arc4random() & 0xffff;
+		priv->dp_inkey = shuffle_generate16(&relay_shuffle);
 		priv->dp_outkey = key;
 		return ((void *)priv);
 	}
blob - b9b81a707abfb452140c5fa1b7573396b1713f64
blob + 1979e4285fa11a32c3e5843095a6a2fe9db72669
--- relayd.h
+++ relayd.h
@@ -1,4 +1,4 @@
-/*	$OpenBSD: relayd.h,v 1.105 2008/07/09 14:57:01 reyk Exp $	*/
+/*	$OpenBSD: relayd.h,v 1.106 2008/07/09 17:16:51 reyk Exp $	*/
 
 /*
  * Copyright (c) 2006, 2007 Pierre-Yves Ritschard <pyr@openbsd.org>
@@ -64,6 +64,12 @@
 #define DPRINTF(x...)	do {} while(0)
 #endif
 
+/* Used for DNS request ID randomization */
+struct shuffle {
+	u_int16_t	 id_shuffle[65536];
+	int		 isindex;
+};
+
 /* buffer */
 struct buf {
 	TAILQ_ENTRY(buf)	 entry;
@@ -801,6 +807,7 @@ SPLAY_PROTOTYPE(session_tree, session, se_nodes, relay
 
 /* relay_udp.c */
 void	 relay_udp_privinit(struct relayd *, struct relay *);
+void	 relay_udp_init(struct relay *);
 int	 relay_udp_bind(struct sockaddr_storage *, in_port_t,
 	    struct protocol *);
 void	 relay_udp_server(int, short, void *);
@@ -871,3 +878,8 @@ void		 pn_ref(u_int16_t);
 void	 snmp_init(struct relayd *, struct imsgbuf *);
 int	 snmp_sendsock(struct imsgbuf *);
 void	 snmp_hosttrap(struct table *, struct host *);
+
+/* shuffle.c */
+void		shuffle_init(struct shuffle *);
+u_int16_t	shuffle_generate16(struct shuffle *);
+
blob - /dev/null
blob + a6ce822f9b274311c0bedc3b97419045fd2212f9 (mode 644)
--- /dev/null
+++ shuffle.c
@@ -0,0 +1,75 @@
+/*	$OpenBSD: shuffle.c,v 1.1 2008/07/09 17:16:51 reyk Exp $	*/
+
+/*
+ * Portions Copyright (C) 2008 Theo de Raadt
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
+ * INTERNET SOFTWARE CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+ * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
+ * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* based on: bind/lib/isc/shuffle.c,v 1.4 2008/07/09 17:07:32 reyk Exp $ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <arpa/inet.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <event.h>
+#include <assert.h>
+
+#include <openssl/ssl.h>
+
+#include "relayd.h"
+
+#define VALID_SHUFFLE(x)	(x != NULL)
+
+void
+shuffle_init(struct shuffle *shuffle)
+{
+	int i, i2;
+
+	assert(VALID_SHUFFLE(shuffle));
+
+	shuffle->isindex = 0;
+	/* Initialize using a Knuth shuffle */
+	for (i = 0; i < 65536; ++i) {
+		i2 = arc4random_uniform(i + 1);
+		shuffle->id_shuffle[i] = shuffle->id_shuffle[i2];
+		shuffle->id_shuffle[i2] = i;
+	}
+}
+
+u_int16_t
+shuffle_generate16(struct shuffle *shuffle)
+{
+	u_int32_t si;
+	u_int16_t r;
+	int i, i2;
+
+	assert(VALID_SHUFFLE(shuffle));
+
+	do {
+		si = arc4random();
+		i = shuffle->isindex & 0xFFFF;
+		i2 = (shuffle->isindex - (si & 0x7FFF)) & 0xFFFF;
+		r = shuffle->id_shuffle[i];
+		shuffle->id_shuffle[i] = shuffle->id_shuffle[i2];
+		shuffle->id_shuffle[i2] = r;
+		shuffle->isindex++;
+	} while (r == 0);
+
+	return (r);
+}