summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKen Raeburn <raeburn@mit.edu>2002-03-12 03:00:08 +0000
committerKen Raeburn <raeburn@mit.edu>2002-03-12 03:00:08 +0000
commitb90ed64cbbb82265fa19561ba0b8bb3e64241d83 (patch)
treeb5f8d7819e58c7a2a32d33ae235d29332d007379 /src
parent298b7b16036beec83b74e0c4160bc69b67264b35 (diff)
downloadkrb5-b90ed64cbbb82265fa19561ba0b8bb3e64241d83.tar.gz
krb5-b90ed64cbbb82265fa19561ba0b8bb3e64241d83.tar.xz
krb5-b90ed64cbbb82265fa19561ba0b8bb3e64241d83.zip
Handle IPv6 sockets that are used to communicate over IPv4, and permit use of
non-IPv4 addresses if address checking is turned off. git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@14260 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src')
-rw-r--r--src/lib/krb4/ChangeLog18
-rw-r--r--src/lib/krb4/mk_priv.c99
-rw-r--r--src/lib/krb4/mk_safe.c30
-rw-r--r--src/lib/krb4/rd_priv.c52
-rw-r--r--src/lib/krb4/rd_safe.c51
5 files changed, 182 insertions, 68 deletions
diff --git a/src/lib/krb4/ChangeLog b/src/lib/krb4/ChangeLog
index 881f09fb1..2072e45de 100644
--- a/src/lib/krb4/ChangeLog
+++ b/src/lib/krb4/ChangeLog
@@ -1,3 +1,21 @@
+2002-03-11 Ken Raeburn <raeburn@mit.edu>
+
+ Handle IPv6 sockets that are used to communicate over IPv4, and
+ permit use of non-IPv4 addresses if address checking is turned
+ off:
+ * mk_priv.c (krb4int_address_less): New function. Compares IPv4
+ addresses for ordering, but also handles the IPv6 v4-mapped form.
+ (krb_mk_priv): Use krb4int_address_less. Handle sender/receiver
+ addresses that are IPv6 v4-mapped like IPv4 addresses, or store
+ zero for other addresses.
+ * mk_safe.c (krb_mk_safe): Use krb4int_address_less. Handle
+ sender/receiver addresses that are IPv6 v4-mapped like IPv4
+ addresses, or store zero for other addresses.
+ * rd_priv.c (krb_rd_priv): Use krb4int_address_less. Deal with
+ socket addresses that are v4-mapped IPv6 addresses.
+ * rd_safe.c (krb_rd_safe): Use krb4int_address_less. Deal with
+ socket addresses that are v4-mapped IPv6 addresses.
+
2001-10-09 Ken Raeburn <raeburn@mit.edu>
* cr_tkt.c, decomp_tkt.c, g_in_tkt.c, tf_util.c: Make prototypes
diff --git a/src/lib/krb4/mk_priv.c b/src/lib/krb4/mk_priv.c
index bc9f9bcf1..41a1a708f 100644
--- a/src/lib/krb4/mk_priv.c
+++ b/src/lib/krb4/mk_priv.c
@@ -93,6 +93,72 @@ extern int krb_debug;
#endif
*/
+/* Utility function:
+
+ Determine order of addresses, if SENDER less than RECEIVER return 1
+ so caller will negate timestamp. Return -1 for failure. */
+int
+krb4int_address_less (struct sockaddr_in *sender, struct sockaddr_in *receiver)
+{
+ unsigned long sender_addr, receiver_addr;
+ unsigned short sender_port, receiver_port;
+ switch (sender->sin_family) {
+ case AF_INET:
+ sender_addr = sender->sin_addr.s_addr;
+ sender_port = sender->sin_port;
+ break;
+#ifdef KRB5_USE_INET6
+ case AF_INET6:
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) sender;
+ if (IN6_IS_ADDR_V4MAPPED (s6)) {
+ struct sockaddr_in sintmp = { 0 };
+ memcpy (&sintmp.sin_addr.s_addr,
+ 12+(char*)&s6->sin6_addr.s6_addr,
+ 4);
+ sender_addr = sintmp.sin_addr.s_addr;
+ } else
+ return -1;
+ sender_port = s6->sin6_port;
+ break;
+#endif
+ default:
+ return -1;
+ }
+ switch (receiver->sin_family) {
+ case AF_INET:
+ receiver_addr = receiver->sin_addr.s_addr;
+ receiver_port = receiver->sin_port;
+ break;
+#ifdef KRB5_USE_INET6
+ case AF_INET6:
+ struct sockaddr_in6 *s6 = (struct sockaddr_in6 *) receiver;
+ if (IN6_IS_ADDR_V4MAPPED (s6)) {
+ struct sockaddr_in sintmp = { 0 };
+ memcpy (&sintmp.sin_addr.s_addr,
+ 12+(char*)&s6->sin6_addr.s6_addr,
+ 4);
+ receiver_addr = sintmp.sin_addr.s_addr;
+ } else
+ return -1;
+ receiver_port = s6->sin6_port;
+ break;
+#endif
+ default:
+ return -1;
+ }
+ /* For compatibility with broken old code, compares are done in
+ VAX byte order (LSBFIRST). */
+ if (lsb_net_ulong_less(sender_addr, receiver_addr) == -1
+ || (lsb_net_ulong_less(sender_addr, receiver_addr) == 0
+ && lsb_net_ushort_less(sender_port, receiver_port) == -1))
+ return 1;
+ return 0;
+ /*
+ * all that for one tiny bit! Heaven help those that talk to
+ * themselves.
+ */
+}
+
long KRB5_CALLCONV
krb_mk_priv(in, out, length, schedule, key, sender, receiver)
u_char *in; /* application data */
@@ -155,24 +221,33 @@ krb_mk_priv(in, out, length, schedule, key, sender, receiver)
*p++ = msg_time_5ms;
/* stuff source address */
- memcpy(p, &sender->sin_addr.s_addr,
- sizeof(sender->sin_addr.s_addr));
+ if (sender->sin_family == AF_INET)
+ memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr));
+#ifdef KRB5_USE_INET6
+ else if (sender->sin_family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr))
+ memcpy(p, 12+(char*)&((struct sockaddr_in6 *)sender)->sin6_addr, 4);
+#endif
+ else
+ /* The address isn't one we can encode in 4 bytes -- but
+ that's okay if the receiver doesn't care. */
+ memset(p, 0, 4);
p += sizeof(sender->sin_addr.s_addr);
/*
* direction bit is the sign bit of the timestamp. Ok
* until 2038??
*/
- /* For compatibility with broken old code, compares are done in VAX
- byte order (LSBFIRST) */
- if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
- receiver->sin_addr.s_addr) == -1)
- msg_time_sec = -msg_time_sec;
- else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr) == 0)
- if (lsb_net_ushort_less(sender->sin_port,
- receiver->sin_port) == -1)
- msg_time_sec = -msg_time_sec;
+ switch (krb4int_address_less (sender, receiver)) {
+ case 1:
+ msg_time_sec = -msg_time_sec;
+ break;
+ case -1:
+ /* Which way should we go in this case? */
+ case 0:
+ break;
+ }
+
/* stuff time sec */
KRB4_PUT32BE(p, msg_time_sec);
diff --git a/src/lib/krb4/mk_safe.c b/src/lib/krb4/mk_safe.c
index f4bb0a660..b797a6a85 100644
--- a/src/lib/krb4/mk_safe.c
+++ b/src/lib/krb4/mk_safe.c
@@ -127,29 +127,25 @@ krb_mk_safe(in, out, length, key, sender, receiver)
*p++ = msg_time_5ms;
/* stuff source address */
- memcpy(p, &sender->sin_addr.s_addr,
- sizeof(sender->sin_addr.s_addr));
+ if (sender->sin_family == AF_INET)
+ memcpy(p, &sender->sin_addr.s_addr, sizeof(sender->sin_addr.s_addr));
+#ifdef KRB5_USE_INET6
+ else if (sender->sin_family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr))
+ memcpy(p, 12+(char*)&((struct sockaddr_in6 *)sender)->sin6_addr, 4);
+#endif
+ else
+ /* The address isn't one we can encode in 4 bytes -- but
+ that's okay if the receiver doesn't care. */
+ memset(p, 0, 4);
p += sizeof(sender->sin_addr.s_addr);
/*
* direction bit is the sign bit of the timestamp. Ok until
* 2038??
*/
- /* For compatibility with broken old code, compares are done in VAX
- byte order (LSBFIRST) */
- if (lsb_net_ulong_less(sender->sin_addr.s_addr, /* src < recv */
- receiver->sin_addr.s_addr) == -1)
- msg_time_sec = -msg_time_sec;
- else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr) == 0)
- if (lsb_net_ushort_less(sender->sin_port,
- receiver->sin_port) == -1)
- msg_time_sec = -msg_time_sec;
- /*
- * all that for one tiny bit! Heaven help those that talk to
- * themselves.
- */
-
+ if (krb4int_address_less (sender, receiver) == 1)
+ msg_time_sec = -msg_time_sec;
/* stuff time sec */
KRB4_PUT32BE(p, msg_time_sec);
diff --git a/src/lib/krb4/rd_priv.c b/src/lib/krb4/rd_priv.c
index e7b42a0fa..6fcce6205 100644
--- a/src/lib/krb4/rd_priv.c
+++ b/src/lib/krb4/rd_priv.c
@@ -154,9 +154,26 @@ krb_rd_priv(in, in_length, schedule, key, sender, receiver, m_data)
/* don't swap, net order always */
p += sizeof(src_addr.s_addr);
- if (!krb_ignore_ip_address
- && src_addr.s_addr != sender->sin_addr.s_addr)
- return RD_AP_MODIFIED;
+ if (!krb_ignore_ip_address) {
+ switch (sender->sin_family) {
+ case AF_INET:
+ if (src_addr.s_addr != sender->sin_addr.s_addr)
+ return RD_AP_MODIFIED;
+ break;
+#ifdef KRB5_USE_INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr)
+ && !memcmp (&src_addr.s_addr,
+ 12 + (char *) &((struct sockaddr_in6 *)sender)->sin6_addr,
+ 4))
+ break;
+ /* Not v4 mapped? Not ignoring addresses? You lose. */
+ return RD_AP_MODIFIED;
+#endif
+ default:
+ return RD_AP_MODIFIED;
+ }
+ }
/* safely get time_sec */
KRB4_GET32(m_data->time_sec, p, le);
@@ -169,31 +186,26 @@ krb_rd_priv(in, in_length, schedule, key, sender, receiver, m_data)
back to the receiver, but most higher level protocols can deal
with that more directly. */
if (krb_ignore_ip_address) {
- if (m_data->time_sec < 0)
- m_data->time_sec = -m_data->time_sec;
- } else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr) == -1)
- /* src < recv */
- m_data->time_sec = -m_data->time_sec;
- else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr) == 0)
- if (lsb_net_ushort_less(sender->sin_port,
- receiver->sin_port) == -1)
- /* src < recv */
+ if (m_data->time_sec < 0)
m_data->time_sec = -m_data->time_sec;
- /*
- * all that for one tiny bit!
- * Heaven help those that talk to themselves.
- */
+ } else
+ switch (krb4int_address_less (sender, receiver)) {
+ case 1:
+ m_data->time_sec = -m_data->time_sec;
+ break;
+ case -1:
+ if (m_data->time_sec < 0)
+ m_data->time_sec = -m_data->time_sec;
+ break;
+ }
/* check the time integrity of the msg */
t_local = TIME_GMT_UNIXSEC;
delta_t = t_local - m_data->time_sec;
if (delta_t < 0)
delta_t = -delta_t; /* Absolute value of difference */
- if (delta_t > CLOCK_SKEW) {
+ if (delta_t > CLOCK_SKEW)
return RD_AP_TIME; /* XXX should probably be better code */
- }
DEB(("\ndelta_t = %d", delta_t));
/*
diff --git a/src/lib/krb4/rd_safe.c b/src/lib/krb4/rd_safe.c
index 40766ba52..f3cc584c1 100644
--- a/src/lib/krb4/rd_safe.c
+++ b/src/lib/krb4/rd_safe.c
@@ -124,9 +124,26 @@ krb_rd_safe(in,in_length,key,sender,receiver,m_data)
/* don't swap, net order always */
p += sizeof(src_addr.s_addr);
- if (!krb_ignore_ip_address
- && src_addr.s_addr != sender->sin_addr.s_addr)
- return RD_AP_MODIFIED;
+ if (!krb_ignore_ip_address) {
+ switch (sender->sin_family) {
+ case AF_INET:
+ if (src_addr.s_addr != sender->sin_addr.s_addr)
+ return RD_AP_MODIFIED;
+ break;
+#ifdef KRB5_USE_INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED (&((struct sockaddr_in6 *)sender)->sin6_addr)
+ && !memcmp (&src_addr.s_addr,
+ 12 + (char *) &((struct sockaddr_in6 *)sender)->sin6_addr,
+ 4))
+ break;
+ /* Not v4 mapped? Not ignoring addresses? You lose. */
+ return RD_AP_MODIFIED;
+#endif
+ default:
+ return RD_AP_MODIFIED;
+ }
+ }
/* safely get time_sec */
KRB4_GET32(m_data->time_sec, p, le);
@@ -139,22 +156,18 @@ krb_rd_safe(in,in_length,key,sender,receiver,m_data)
back to the receiver, but most higher level protocols can deal
with that more directly. */
if (krb_ignore_ip_address) {
- if (m_data->time_sec <0)
- m_data->time_sec = -m_data->time_sec;
- } else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr)==-1)
- /* src < recv */
- m_data->time_sec = - m_data->time_sec;
- else if (lsb_net_ulong_less(sender->sin_addr.s_addr,
- receiver->sin_addr.s_addr)==0)
- if (lsb_net_ushort_less(sender->sin_port,receiver->sin_port)==-1)
- /* src < recv */
- m_data->time_sec = - m_data->time_sec;
-
- /*
- * All that for one tiny bit! Heaven help those that talk to
- * themselves.
- */
+ if (m_data->time_sec < 0)
+ m_data->time_sec = -m_data->time_sec;
+ } else
+ switch (krb4int_address_less (sender, receiver)) {
+ case 1:
+ m_data->time_sec = -m_data->time_sec;
+ break;
+ case -1:
+ if (m_data->time_sec < 0)
+ m_data->time_sec = -m_data->time_sec;
+ break;
+ }
/* check the time integrity of the msg */
t_local = TIME_GMT_UNIXSEC;