summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Beck <beck@cvs.openbsd.org>2005-04-20 20:28:55 +0000
committerBob Beck <beck@cvs.openbsd.org>2005-04-20 20:28:55 +0000
commit81f181d604d7310280878c440cccb92f30db532a (patch)
tree3a66fbbe5a8adfe76e76ef0e801847054c593396
parent0133950253919ad3f20cba87a9b2c82dcfaf2692 (diff)
fix snprintf and strlcpy abuse, returning the string length is at least
save in the case where this is being used in pointer arithmatic ok cloder@
-rw-r--r--kerberosV/src/lib/krb5/addr_families.c667
-rw-r--r--kerberosV/src/lib/krb5/get_host_realm.c74
2 files changed, 614 insertions, 127 deletions
diff --git a/kerberosV/src/lib/krb5/addr_families.c b/kerberosV/src/lib/krb5/addr_families.c
index 2d5d265b67f..5354f33ec39 100644
--- a/kerberosV/src/lib/krb5/addr_families.c
+++ b/kerberosV/src/lib/krb5/addr_families.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997-1999 Kungliga Tekniska H�gskolan
+ * Copyright (c) 1997-2003 Kungliga Tekniska H�gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -33,7 +33,7 @@
#include "krb5_locl.h"
-RCSID("$KTH: addr_families.c,v 1.24 2000/07/08 13:05:43 joda Exp $");
+RCSID("$KTH: addr_families.c,v 1.38 2003/03/25 12:37:02 joda Exp $");
struct addr_operations {
int af;
@@ -42,13 +42,16 @@ struct addr_operations {
krb5_error_code (*sockaddr2addr)(const struct sockaddr *, krb5_address *);
krb5_error_code (*sockaddr2port)(const struct sockaddr *, int16_t *);
void (*addr2sockaddr)(const krb5_address *, struct sockaddr *,
- int *sa_size, int port);
- void (*h_addr2sockaddr)(const char *, struct sockaddr *, int *, int);
+ krb5_socklen_t *sa_size, int port);
+ void (*h_addr2sockaddr)(const char *, struct sockaddr *, krb5_socklen_t *, int);
krb5_error_code (*h_addr2addr)(const char *, krb5_address *);
krb5_boolean (*uninteresting)(const struct sockaddr *);
- void (*anyaddr)(struct sockaddr *, int *, int);
+ void (*anyaddr)(struct sockaddr *, krb5_socklen_t *, int);
int (*print_addr)(const krb5_address *, char *, size_t);
- int (*parse_addr)(const char*, krb5_address *);
+ int (*parse_addr)(krb5_context, const char*, krb5_address *);
+ int (*order_addr)(krb5_context, const krb5_address*, const krb5_address*);
+ int (*free_addr)(krb5_context, krb5_address*);
+ int (*copy_addr)(krb5_context, const krb5_address*, krb5_address*);
};
/*
@@ -78,29 +81,33 @@ ipv4_sockaddr2port (const struct sockaddr *sa, int16_t *port)
static void
ipv4_addr2sockaddr (const krb5_address *a,
struct sockaddr *sa,
- int *sa_size,
+ krb5_socklen_t *sa_size,
int port)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
- memset (sin, 0, sizeof(*sin));
- sin->sin_family = AF_INET;
- memcpy (&sin->sin_addr, a->address.data, 4);
- sin->sin_port = port;
- *sa_size = sizeof(*sin);
+ struct sockaddr_in tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin_family = AF_INET;
+ memcpy (&tmp.sin_addr, a->address.data, 4);
+ tmp.sin_port = port;
+ memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+ *sa_size = sizeof(tmp);
}
static void
ipv4_h_addr2sockaddr(const char *addr,
- struct sockaddr *sa, int *sa_size, int port)
+ struct sockaddr *sa,
+ krb5_socklen_t *sa_size,
+ int port)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
- memset (sin, 0, sizeof(*sin));
- *sa_size = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = port;
- sin->sin_addr = *((const struct in_addr *)addr);
+ struct sockaddr_in tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin_family = AF_INET;
+ tmp.sin_port = port;
+ tmp.sin_addr = *((const struct in_addr *)addr);
+ memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+ *sa_size = sizeof(tmp);
}
static krb5_error_code
@@ -130,15 +137,16 @@ ipv4_uninteresting (const struct sockaddr *sa)
}
static void
-ipv4_anyaddr (struct sockaddr *sa, int *sa_size, int port)
+ipv4_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
{
- struct sockaddr_in *sin = (struct sockaddr_in *)sa;
-
- memset (sin, 0, sizeof(*sin));
- *sa_size = sizeof(*sin);
- sin->sin_family = AF_INET;
- sin->sin_port = port;
- sin->sin_addr.s_addr = INADDR_ANY;
+ struct sockaddr_in tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin_family = AF_INET;
+ tmp.sin_port = port;
+ tmp.sin_addr.s_addr = INADDR_ANY;
+ memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+ *sa_size = sizeof(tmp);
}
static int
@@ -146,13 +154,17 @@ ipv4_print_addr (const krb5_address *addr, char *str, size_t len)
{
struct in_addr ia;
+ if (len == 0)
+ return(0);
+
memcpy (&ia, addr->address.data, 4);
- return snprintf (str, len, "IPv4:%s", inet_ntoa(ia));
+ (void) snprintf (str, len, "IPv4:%s", inet_ntoa(ia));
+ return(strlen(str));
}
static int
-ipv4_parse_addr (const char *address, krb5_address *addr)
+ipv4_parse_addr (krb5_context context, const char *address, krb5_address *addr)
{
const char *p;
struct in_addr a;
@@ -228,31 +240,33 @@ ipv6_sockaddr2port (const struct sockaddr *sa, int16_t *port)
static void
ipv6_addr2sockaddr (const krb5_address *a,
struct sockaddr *sa,
- int *sa_size,
+ krb5_socklen_t *sa_size,
int port)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
-
- memset (sin6, 0, sizeof(*sin6));
- sin6->sin6_family = AF_INET6;
- memcpy (&sin6->sin6_addr, a->address.data, sizeof(sin6->sin6_addr));
- sin6->sin6_port = port;
- *sa_size = sizeof(*sin6);
+ struct sockaddr_in6 tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin6_family = AF_INET6;
+ memcpy (&tmp.sin6_addr, a->address.data, sizeof(tmp.sin6_addr));
+ tmp.sin6_port = port;
+ memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+ *sa_size = sizeof(tmp);
}
static void
ipv6_h_addr2sockaddr(const char *addr,
struct sockaddr *sa,
- int *sa_size,
+ krb5_socklen_t *sa_size,
int port)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
-
- memset (sin6, 0, sizeof(*sin6));
- *sa_size = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = port;
- sin6->sin6_addr = *((const struct in6_addr *)addr);
+ struct sockaddr_in6 tmp;
+
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin6_family = AF_INET6;
+ tmp.sin6_port = port;
+ tmp.sin6_addr = *((const struct in6_addr *)addr);
+ memcpy(sa, &tmp, min(sizeof(tmp), *sa_size));
+ *sa_size = sizeof(tmp);
}
static krb5_error_code
@@ -279,44 +293,44 @@ ipv6_uninteresting (const struct sockaddr *sa)
}
static void
-ipv6_anyaddr (struct sockaddr *sa, int *sa_size, int port)
+ipv6_anyaddr (struct sockaddr *sa, krb5_socklen_t *sa_size, int port)
{
- struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)sa;
+ struct sockaddr_in6 tmp;
- memset (sin6, 0, sizeof(*sin6));
- *sa_size = sizeof(*sin6);
- sin6->sin6_family = AF_INET6;
- sin6->sin6_port = port;
- sin6->sin6_addr = in6addr_any;
+ memset (&tmp, 0, sizeof(tmp));
+ tmp.sin6_family = AF_INET6;
+ tmp.sin6_port = port;
+ tmp.sin6_addr = in6addr_any;
+ *sa_size = sizeof(tmp);
}
static int
ipv6_print_addr (const krb5_address *addr, char *str, size_t len)
{
- char buf[128], buf2[3];
-#ifdef HAVE_INET_NTOP
+ char buf[128];
if(inet_ntop(AF_INET6, addr->address.data, buf, sizeof(buf)) == NULL)
-#endif
- {
- /* XXX this is pretty ugly, but better than abort() */
- int i;
- unsigned char *p = addr->address.data;
- buf[0] = '\0';
- for(i = 0; i < addr->address.length; i++) {
- snprintf(buf2, sizeof(buf2), "%02x", p[i]);
- if(i > 0 && (i & 1) == 0)
- strlcat(buf, ":", sizeof(buf));
- strlcat(buf, buf2, sizeof(buf));
- }
- }
- return snprintf(str, len, "IPv6:%s", buf);
+ return (0);
+ if (len == 0)
+ return(0);
+ (void) snprintf(str, len, "IPv6:%s", buf);
+ return(strlen(str));
}
static int
-ipv6_parse_addr (const char *address, krb5_address *addr)
+ipv6_parse_addr (krb5_context context, const char *address, krb5_address *addr)
{
int ret;
struct in6_addr in6;
+ const char *p;
+
+ p = strchr(address, ':');
+ if(p) {
+ p++;
+ if(strncasecmp(address, "ip6:", p - address) == 0 ||
+ strncasecmp(address, "ipv6:", p - address) == 0 ||
+ strncasecmp(address, "inet6:", p - address) == 0)
+ address = p;
+ }
ret = inet_pton(AF_INET6, address, &in6.s6_addr);
if(ret == 1) {
@@ -336,6 +350,200 @@ ipv6_parse_addr (const char *address, krb5_address *addr)
* table
*/
+#define KRB5_ADDRESS_ARANGE (-100)
+
+struct arange {
+ krb5_address low;
+ krb5_address high;
+};
+
+static int
+arange_parse_addr (krb5_context context,
+ const char *address, krb5_address *addr)
+{
+ char buf[1024];
+ krb5_addresses low, high;
+ struct arange *a;
+ krb5_error_code ret;
+
+ if(strncasecmp(address, "RANGE:", 6) != 0)
+ return -1;
+
+ address += 6;
+
+ /* should handle netmasks */
+ strsep_copy(&address, "-", buf, sizeof(buf));
+ ret = krb5_parse_address(context, buf, &low);
+ if(ret)
+ return ret;
+ if(low.len != 1) {
+ krb5_free_addresses(context, &low);
+ return -1;
+ }
+
+ strsep_copy(&address, "-", buf, sizeof(buf));
+ ret = krb5_parse_address(context, buf, &high);
+ if(ret) {
+ krb5_free_addresses(context, &low);
+ return ret;
+ }
+
+ if(high.len != 1 || high.val[0].addr_type != low.val[0].addr_type) {
+ krb5_free_addresses(context, &low);
+ krb5_free_addresses(context, &high);
+ return -1;
+ }
+
+ krb5_data_alloc(&addr->address, sizeof(*a));
+ addr->addr_type = KRB5_ADDRESS_ARANGE;
+ a = addr->address.data;
+
+ if(krb5_address_order(context, &low.val[0], &high.val[0]) < 0) {
+ a->low = low.val[0];
+ a->high = high.val[0];
+ } else {
+ a->low = high.val[0];
+ a->high = low.val[0];
+ }
+ return 0;
+}
+
+static int
+arange_free (krb5_context context, krb5_address *addr)
+{
+ struct arange *a;
+ a = addr->address.data;
+ krb5_free_address(context, &a->low);
+ krb5_free_address(context, &a->high);
+ return 0;
+}
+
+
+static int
+arange_copy (krb5_context context, const krb5_address *inaddr,
+ krb5_address *outaddr)
+{
+ krb5_error_code ret;
+ struct arange *i, *o;
+
+ outaddr->addr_type = KRB5_ADDRESS_ARANGE;
+ ret = krb5_data_alloc(&outaddr->address, sizeof(*o));
+ if(ret)
+ return ret;
+ i = inaddr->address.data;
+ o = outaddr->address.data;
+ ret = krb5_copy_address(context, &i->low, &o->low);
+ if(ret) {
+ krb5_data_free(&outaddr->address);
+ return ret;
+ }
+ ret = krb5_copy_address(context, &i->high, &o->high);
+ if(ret) {
+ krb5_free_address(context, &o->low);
+ krb5_data_free(&outaddr->address);
+ return ret;
+ }
+ return 0;
+}
+
+static int
+arange_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+ struct arange *a;
+ krb5_error_code ret;
+ size_t l, ret_len = 0;
+
+ if (len == 0)
+ return(0);
+
+ a = addr->address.data;
+
+ (void) strlcpy(str, "RANGE:", len);
+ ret_len += strlen(str); /* truncate if too long */
+
+ ret = krb5_print_address (&a->low, str + ret_len, len - ret_len, &l);
+ ret_len += l;
+
+ (void) strlcat(str, "-", len);
+ ret_len += strlen(str); /* truncate if too long */
+
+ ret = krb5_print_address (&a->high, str + ret_len, len - ret_len, &l);
+ ret_len += l;
+
+ return ret_len;
+}
+
+static int
+arange_order_addr(krb5_context context,
+ const krb5_address *addr1,
+ const krb5_address *addr2)
+{
+ int tmp1, tmp2, sign;
+ struct arange *a;
+ const krb5_address *a2;
+
+ if(addr1->addr_type == KRB5_ADDRESS_ARANGE) {
+ a = addr1->address.data;
+ a2 = addr2;
+ sign = 1;
+ } else if(addr2->addr_type == KRB5_ADDRESS_ARANGE) {
+ a = addr2->address.data;
+ a2 = addr1;
+ sign = -1;
+ } else
+ abort();
+
+ if(a2->addr_type == KRB5_ADDRESS_ARANGE) {
+ struct arange *b = a2->address.data;
+ tmp1 = krb5_address_order(context, &a->low, &b->low);
+ if(tmp1 != 0)
+ return sign * tmp1;
+ return sign * krb5_address_order(context, &a->high, &b->high);
+ } else if(a2->addr_type == a->low.addr_type) {
+ tmp1 = krb5_address_order(context, &a->low, a2);
+ if(tmp1 > 0)
+ return sign;
+ tmp2 = krb5_address_order(context, &a->high, a2);
+ if(tmp2 < 0)
+ return -sign;
+ return 0;
+ } else {
+ return sign * (addr1->addr_type - addr2->addr_type);
+ }
+}
+
+static int
+addrport_print_addr (const krb5_address *addr, char *str, size_t len)
+{
+ krb5_address addr1, addr2;
+ uint16_t port = 0;
+ size_t ret_len = 0, l;
+ krb5_storage *sp = krb5_storage_from_data((krb5_data*)&addr->address);
+ /* for totally obscure reasons, these are not in network byteorder */
+ krb5_storage_set_byteorder(sp, KRB5_STORAGE_BYTEORDER_LE);
+
+ krb5_storage_seek(sp, 2, SEEK_CUR); /* skip first two bytes */
+ krb5_ret_address(sp, &addr1);
+
+ krb5_storage_seek(sp, 2, SEEK_CUR); /* skip two bytes */
+ krb5_ret_address(sp, &addr2);
+ krb5_storage_free(sp);
+ if(addr2.addr_type == KRB5_ADDRESS_IPPORT && addr2.address.length == 2) {
+ unsigned long value;
+ _krb5_get_int(addr2.address.data, &value, 2);
+ port = value;
+ }
+ l = strlcpy(str, "ADDRPORT:", len);
+ ret_len += strlen(str); /* truncate if too long */
+ krb5_print_address(&addr1, str + ret_len, len - ret_len, &l);
+ ret_len += l;
+ /* XXX oh the horror */
+ if ((len - ret_len) == 0)
+ return(ret_len);
+ (void) snprintf(str + ret_len, len - ret_len, ",PORT=%u", port);
+ return(strlen(str));
+}
+
static struct addr_operations at[] = {
{AF_INET, KRB5_ADDRESS_INET, sizeof(struct sockaddr_in),
ipv4_sockaddr2addr,
@@ -351,8 +559,16 @@ static struct addr_operations at[] = {
ipv6_addr2sockaddr,
ipv6_h_addr2sockaddr,
ipv6_h_addr2addr,
- ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr}
+ ipv6_uninteresting, ipv6_anyaddr, ipv6_print_addr, ipv6_parse_addr} ,
#endif
+ {KRB5_ADDRESS_ADDRPORT, KRB5_ADDRESS_ADDRPORT, 0,
+ NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, addrport_print_addr, NULL, NULL, NULL, NULL },
+ /* fake address type */
+ {KRB5_ADDRESS_ARANGE, KRB5_ADDRESS_ARANGE, sizeof(struct arange),
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ arange_print_addr, arange_parse_addr,
+ arange_order_addr, arange_free, arange_copy }
};
static int num_addrs = sizeof(at) / sizeof(at[0]);
@@ -386,33 +602,50 @@ find_atype(int atype)
}
krb5_error_code
-krb5_sockaddr2address (const struct sockaddr *sa, krb5_address *addr)
+krb5_sockaddr2address (krb5_context context,
+ const struct sockaddr *sa, krb5_address *addr)
{
struct addr_operations *a = find_af(sa->sa_family);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported",
+ sa->sa_family);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
return (*a->sockaddr2addr)(sa, addr);
}
krb5_error_code
-krb5_sockaddr2port (const struct sockaddr *sa, int16_t *port)
+krb5_sockaddr2port (krb5_context context,
+ const struct sockaddr *sa, int16_t *port)
{
struct addr_operations *a = find_af(sa->sa_family);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported",
+ sa->sa_family);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
return (*a->sockaddr2port)(sa, port);
}
krb5_error_code
-krb5_addr2sockaddr (const krb5_address *addr,
+krb5_addr2sockaddr (krb5_context context,
+ const krb5_address *addr,
struct sockaddr *sa,
- int *sa_size,
+ krb5_socklen_t *sa_size,
int port)
{
struct addr_operations *a = find_atype(addr->addr_type);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address type %d not supported",
+ addr->addr_type);
+ return KRB5_PROG_ATYPE_NOSUPP;
+ }
+ if (a->addr2sockaddr == NULL) {
+ krb5_set_error_string (context, "Can't convert address type %d to sockaddr",
+ addr->addr_type);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
(*a->addr2sockaddr)(addr, sa, sa_size, port);
return 0;
}
@@ -433,43 +666,53 @@ krb5_boolean
krb5_sockaddr_uninteresting(const struct sockaddr *sa)
{
struct addr_operations *a = find_af(sa->sa_family);
- if (a == NULL)
+ if (a == NULL || a->uninteresting == NULL)
return TRUE;
return (*a->uninteresting)(sa);
}
krb5_error_code
-krb5_h_addr2sockaddr (int af,
- const char *addr, struct sockaddr *sa, int *sa_size,
+krb5_h_addr2sockaddr (krb5_context context,
+ int af,
+ const char *addr, struct sockaddr *sa,
+ krb5_socklen_t *sa_size,
int port)
{
struct addr_operations *a = find_af(af);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported", af);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
(*a->h_addr2sockaddr)(addr, sa, sa_size, port);
return 0;
}
krb5_error_code
-krb5_h_addr2addr (int af,
+krb5_h_addr2addr (krb5_context context,
+ int af,
const char *haddr, krb5_address *addr)
{
struct addr_operations *a = find_af(af);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported", af);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
return (*a->h_addr2addr)(haddr, addr);
}
krb5_error_code
-krb5_anyaddr (int af,
+krb5_anyaddr (krb5_context context,
+ int af,
struct sockaddr *sa,
- int *sa_size,
+ krb5_socklen_t *sa_size,
int port)
{
struct addr_operations *a = find_af (af);
- if (a == NULL)
+ if (a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported", af);
return KRB5_PROG_ATYPE_NOSUPP;
+ }
(*a->anyaddr)(sa, sa_size, port);
return 0;
@@ -479,26 +722,52 @@ krb5_error_code
krb5_print_address (const krb5_address *addr,
char *str, size_t len, size_t *ret_len)
{
+ size_t ret;
+ int r = 0;
struct addr_operations *a = find_atype(addr->addr_type);
- if (a == NULL) {
+ if (len == 0) {
+ ret = 0;
+ r = EINVAL;
+ goto out;
+ }
+
+ if (a == NULL || a->print_addr == NULL) {
char *s;
- size_t l;
+ int l;
int i;
+
s = str;
l = snprintf(s, len, "TYPE_%d:", addr->addr_type);
+ if (l < 0 || l > (len - 1)) {
+ ret = 0;
+ r = EINVAL;
+ goto out;
+ }
s += l;
- len -= len;
+ len -= l;
for(i = 0; i < addr->address.length; i++) {
l = snprintf(s, len, "%02x", ((char*)addr->address.data)[i]);
+ if (l < 0 || l > (len - 1)) {
+ ret = 0;
+ r = EINVAL;
+ goto out;
+ }
len -= l;
s += l;
}
- *ret_len = s - str;
- return 0;
+ ret = s - str;
+ goto out;
}
- *ret_len = (*a->print_addr)(addr, str, len);
- return 0;
+ ret = (*a->print_addr)(addr, str, len);
+ if (ret <= 0 || ret > (len - 1)) {
+ ret = 0;
+ r = EINVAL;
+ }
+out:
+ if(ret_len != NULL)
+ *ret_len = ret;
+ return r;
}
krb5_error_code
@@ -509,21 +778,25 @@ krb5_parse_address(krb5_context context,
int i, n;
struct addrinfo *ai, *a;
int error;
+ int save_errno;
for(i = 0; i < num_addrs; i++) {
if(at[i].parse_addr) {
- krb5_address a;
- if((*at[i].parse_addr)(string, &a) == 0) {
+ krb5_address addr;
+ if((*at[i].parse_addr)(context, string, &addr) == 0) {
ALLOC_SEQ(addresses, 1);
- addresses->val[0] = a;
+ addresses->val[0] = addr;
return 0;
}
}
}
error = getaddrinfo (string, NULL, NULL, &ai);
- if (error)
- return krb5_eai_to_heim_errno(error);
+ if (error) {
+ save_errno = errno;
+ krb5_set_error_string (context, "%s: %s", string, gai_strerror(error));
+ return krb5_eai_to_heim_errno(error, save_errno);
+ }
n = 0;
for (a = ai; a != NULL; a = a->ai_next)
@@ -531,9 +804,197 @@ krb5_parse_address(krb5_context context,
ALLOC_SEQ(addresses, n);
- for (a = ai, i = 0; a != NULL; a = a->ai_next, ++i) {
- krb5_sockaddr2address (ai->ai_addr, &addresses->val[i]);
+ for (a = ai, i = 0; a != NULL; a = a->ai_next) {
+ if(krb5_sockaddr2address (context, ai->ai_addr,
+ &addresses->val[i]) == 0)
+ i++;
}
freeaddrinfo (ai);
return 0;
}
+
+int
+krb5_address_order(krb5_context context,
+ const krb5_address *addr1,
+ const krb5_address *addr2)
+{
+ /* this sucks; what if both addresses have order functions, which
+ should we call? this works for now, though */
+ struct addr_operations *a;
+ a = find_atype(addr1->addr_type);
+ if(a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported",
+ addr1->addr_type);
+ return KRB5_PROG_ATYPE_NOSUPP;
+ }
+ if(a->order_addr != NULL)
+ return (*a->order_addr)(context, addr1, addr2);
+ a = find_atype(addr2->addr_type);
+ if(a == NULL) {
+ krb5_set_error_string (context, "Address family %d not supported",
+ addr2->addr_type);
+ return KRB5_PROG_ATYPE_NOSUPP;
+ }
+ if(a->order_addr != NULL)
+ return (*a->order_addr)(context, addr1, addr2);
+
+ if(addr1->addr_type != addr2->addr_type)
+ return addr1->addr_type - addr2->addr_type;
+ if(addr1->address.length != addr2->address.length)
+ return addr1->address.length - addr2->address.length;
+ return memcmp (addr1->address.data,
+ addr2->address.data,
+ addr1->address.length);
+}
+
+krb5_boolean
+krb5_address_compare(krb5_context context,
+ const krb5_address *addr1,
+ const krb5_address *addr2)
+{
+ return krb5_address_order (context, addr1, addr2) == 0;
+}
+
+krb5_boolean
+krb5_address_search(krb5_context context,
+ const krb5_address *addr,
+ const krb5_addresses *addrlist)
+{
+ int i;
+
+ for (i = 0; i < addrlist->len; ++i)
+ if (krb5_address_compare (context, addr, &addrlist->val[i]))
+ return TRUE;
+ return FALSE;
+}
+
+krb5_error_code
+krb5_free_address(krb5_context context,
+ krb5_address *address)
+{
+ struct addr_operations *a = find_af (address->addr_type);
+ if(a != NULL && a->free_addr != NULL)
+ return (*a->free_addr)(context, address);
+ krb5_data_free (&address->address);
+ return 0;
+}
+
+krb5_error_code
+krb5_free_addresses(krb5_context context,
+ krb5_addresses *addresses)
+{
+ int i;
+ for(i = 0; i < addresses->len; i++)
+ krb5_free_address(context, &addresses->val[i]);
+ free(addresses->val);
+ return 0;
+}
+
+krb5_error_code
+krb5_copy_address(krb5_context context,
+ const krb5_address *inaddr,
+ krb5_address *outaddr)
+{
+ struct addr_operations *a = find_af (inaddr->addr_type);
+ if(a != NULL && a->copy_addr != NULL)
+ return (*a->copy_addr)(context, inaddr, outaddr);
+ return copy_HostAddress(inaddr, outaddr);
+}
+
+krb5_error_code
+krb5_copy_addresses(krb5_context context,
+ const krb5_addresses *inaddr,
+ krb5_addresses *outaddr)
+{
+ int i;
+ ALLOC_SEQ(outaddr, inaddr->len);
+ if(inaddr->len > 0 && outaddr->val == NULL)
+ return ENOMEM;
+ for(i = 0; i < inaddr->len; i++)
+ krb5_copy_address(context, &inaddr->val[i], &outaddr->val[i]);
+ return 0;
+}
+
+krb5_error_code
+krb5_append_addresses(krb5_context context,
+ krb5_addresses *dest,
+ const krb5_addresses *source)
+{
+ krb5_address *tmp;
+ krb5_error_code ret;
+ int i;
+ if(source->len > 0) {
+ tmp = realloc(dest->val, (dest->len + source->len) * sizeof(*tmp));
+ if(tmp == NULL) {
+ krb5_set_error_string(context, "realloc: out of memory");
+ return ENOMEM;
+ }
+ dest->val = tmp;
+ for(i = 0; i < source->len; i++) {
+ /* skip duplicates */
+ if(krb5_address_search(context, &source->val[i], dest))
+ continue;
+ ret = krb5_copy_address(context,
+ &source->val[i],
+ &dest->val[dest->len]);
+ if(ret)
+ return ret;
+ dest->len++;
+ }
+ }
+ return 0;
+}
+
+/*
+ * Create an address of type KRB5_ADDRESS_ADDRPORT from (addr, port)
+ */
+
+krb5_error_code
+krb5_make_addrport (krb5_context context,
+ krb5_address **res, const krb5_address *addr, int16_t port)
+{
+ krb5_error_code ret;
+ size_t len = addr->address.length + 2 + 4 * 4;
+ u_char *p;
+
+ *res = malloc (sizeof(**res));
+ if (*res == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ return ENOMEM;
+ }
+ (*res)->addr_type = KRB5_ADDRESS_ADDRPORT;
+ ret = krb5_data_alloc (&(*res)->address, len);
+ if (ret) {
+ krb5_set_error_string(context, "malloc: out of memory");
+ free (*res);
+ return ret;
+ }
+ p = (*res)->address.data;
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = (addr->addr_type ) & 0xFF;
+ *p++ = (addr->addr_type >> 8) & 0xFF;
+
+ *p++ = (addr->address.length ) & 0xFF;
+ *p++ = (addr->address.length >> 8) & 0xFF;
+ *p++ = (addr->address.length >> 16) & 0xFF;
+ *p++ = (addr->address.length >> 24) & 0xFF;
+
+ memcpy (p, addr->address.data, addr->address.length);
+ p += addr->address.length;
+
+ *p++ = 0;
+ *p++ = 0;
+ *p++ = (KRB5_ADDRESS_IPPORT ) & 0xFF;
+ *p++ = (KRB5_ADDRESS_IPPORT >> 8) & 0xFF;
+
+ *p++ = (2 ) & 0xFF;
+ *p++ = (2 >> 8) & 0xFF;
+ *p++ = (2 >> 16) & 0xFF;
+ *p++ = (2 >> 24) & 0xFF;
+
+ memcpy (p, &port, 2);
+ p += 2;
+
+ return 0;
+}
diff --git a/kerberosV/src/lib/krb5/get_host_realm.c b/kerberosV/src/lib/krb5/get_host_realm.c
index b1cc2a76db6..92e978cbb92 100644
--- a/kerberosV/src/lib/krb5/get_host_realm.c
+++ b/kerberosV/src/lib/krb5/get_host_realm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 1998, 1999 Kungliga Tekniska H�gskolan
+ * Copyright (c) 1997 - 2001 Kungliga Tekniska H�gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -34,19 +34,19 @@
#include "krb5_locl.h"
#include <resolve.h>
-RCSID("$KTH: get_host_realm.c,v 1.25 1999/12/11 23:14:07 assar Exp $");
+RCSID("$KTH: get_host_realm.c,v 1.29 2002/08/28 13:36:57 nectar Exp $");
/* To automagically find the correct realm of a host (without
* [domain_realm] in krb5.conf) add a text record for your domain with
* the name of your realm, like this:
*
- * krb5-realm IN TXT FOO.SE
+ * _kerberos IN TXT "FOO.SE"
*
* The search is recursive, so you can add entries for specific
* hosts. To find the realm of host a.b.c, it first tries
- * krb5-realm.a.b.c, then krb5-realm.b.c and so on.
+ * _kerberos.a.b.c, then _kerberos.b.c and so on.
*
- * Also supported is _kerberos (following draft-ietf-cat-krb-dns-locate-01.txt)
+ * This method is described in draft-ietf-cat-krb-dns-locate-03.txt.
*
*/
@@ -92,23 +92,33 @@ copy_txt_to_realms (struct resource_record *head,
static int
dns_find_realm(krb5_context context,
const char *domain,
- const char *dom_string,
krb5_realm **realms)
{
+ static char *default_labels[] = { "_kerberos", NULL };
char dom[MAXHOSTNAMELEN];
struct dns_reply *r;
- int ret;
+ char **labels;
+ int i, j, ret;
+ labels = krb5_config_get_strings(context, NULL, "libdefaults",
+ "dns_lookup_realm_labels", NULL);
+ if(labels == NULL)
+ labels = default_labels;
if(*domain == '.')
domain++;
- snprintf(dom, sizeof(dom), "%s.%s.", dom_string, domain);
- r = dns_lookup(dom, "TXT");
- if(r == NULL)
- return -1;
-
- ret = copy_txt_to_realms (r->head, realms);
- dns_free_data(r);
- return ret;
+ for (i = 0; labels[i] != NULL; i++) {
+ j = snprintf(dom, sizeof(dom), "%s.%s.", labels[i], domain);
+ if (j >= sizeof(dom) || j < 0) /* fucking solaris assholes */
+ return -1;
+ r = dns_lookup(dom, "TXT");
+ if(r != NULL) {
+ ret = copy_txt_to_realms (r->head, realms);
+ dns_free_data(r);
+ if(ret == 0)
+ return 0;
+ }
+ }
+ return -1;
}
/*
@@ -142,34 +152,50 @@ config_find_realm(krb5_context context,
krb5_error_code
krb5_get_host_realm_int (krb5_context context,
const char *host,
+ krb5_boolean use_dns,
krb5_realm **realms)
{
- const char *p;
+ const char *p, *q;
+ krb5_boolean dns_locate_enable;
+ dns_locate_enable = krb5_config_get_bool_default(context, NULL, TRUE,
+ "libdefaults", "dns_lookup_realm", NULL);
for (p = host; p != NULL; p = strchr (p + 1, '.')) {
- if(config_find_realm(context, p, realms) == 0)
- return 0;
- else if(dns_find_realm(context, p, "krb5-realm", realms) == 0)
- return 0;
- else if(dns_find_realm(context, p, "_kerberos", realms) == 0)
- return 0;
+ if(config_find_realm(context, p, realms) == 0) {
+ if(strcasecmp(*realms[0], "dns_locate") == 0) {
+ if(use_dns)
+ for (q = host; q != NULL; q = strchr(q + 1, '.'))
+ if(dns_find_realm(context, q, realms) == 0)
+ return 0;
+ continue;
+ } else
+ return 0;
+ }
+ else if(use_dns && dns_locate_enable) {
+ if(dns_find_realm(context, p, realms) == 0)
+ return 0;
+ }
}
p = strchr(host, '.');
if(p != NULL) {
p++;
*realms = malloc(2 * sizeof(krb5_realm));
- if (*realms == NULL)
+ if (*realms == NULL) {
+ krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
+ }
(*realms)[0] = strdup(p);
if((*realms)[0] == NULL) {
free(*realms);
+ krb5_set_error_string(context, "malloc: out of memory");
return ENOMEM;
}
strupr((*realms)[0]);
(*realms)[1] = NULL;
return 0;
}
+ krb5_set_error_string(context, "unable to find realm of host %s", host);
return KRB5_ERR_HOST_REALM_UNKNOWN;
}
@@ -190,5 +216,5 @@ krb5_get_host_realm(krb5_context context,
host = hostname;
}
- return krb5_get_host_realm_int (context, host, realms);
+ return krb5_get_host_realm_int (context, host, 1, realms);
}