-/* $KAME: ipsec_doi.c,v 1.154 2001/12/31 20:13:40 thorpej Exp $ */
+/* $KAME: ipsec_doi.c,v 1.158 2002/09/27 05:55:52 itojun Exp $ */
/*
* Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
#include "crypto_openssl.h"
#include "strnames.h"
#include "gcmalloc.h"
+#include "isakmp_natd.h"
#ifdef HAVE_GSSAPI
#include "gssapi.h"
struct prop_pair *p;
struct isakmpsa *proposal, *sap;
{
-#ifdef YIPS_DEBUG
struct isakmp_pl_p *prop = p->prop;
-#endif
struct isakmp_pl_t *trns = p->trns;
struct isakmpsa sa, *s, *tsap;
/* make a SA to be replayed. */
/* SPI must be updated later. */
iph2->sa_ret = get_sabyproppair(ret, iph2->ph1);
+
free_proppair0(ret);
if (iph2->sa_ret == NULL)
return -1;
switch (lorv) {
case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
case IPSECDOI_ATTR_ENC_MODE_TRNS:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
break;
default:
plog(LLV_ERROR, LOCATION, NULL,
switch (lorv) {
case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
case IPSECDOI_ATTR_ENC_MODE_TRNS:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT:
+ case IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT:
break;
default:
plog(LLV_ERROR, LOCATION, NULL,
propoff = 0;
for (a = proposal; a; a = a->next) {
for (b = a->head; b; b = b->next) {
+#ifdef IKE_NAT_T
+ /*
+ * Hack to fix encmode, we may have detected a nat since
+ * we last set pr->encmode. We need to fix this if
+ * we now have a NAT. NAT-T doesn't work with AH.
+ */
+ int nattype;
+ if (iph2->ph1 && (nattype = natd_hasnat(iph2->ph1)) &&
+ b->proto_id != IPSECDOI_PROTO_IPSEC_AH)
+ {
+ switch (b->encmode)
+ {
+
+ case IPSECDOI_ATTR_ENC_MODE_TUNNEL:
+ if (nattype == natt_type_rfc ||
+ nattype == natt_type_apple)
+ b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC;
+ else
+ b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT;
+ break;
+ case IPSECDOI_ATTR_ENC_MODE_TRNS:
+ if (nattype == natt_type_rfc ||
+ nattype == natt_type_apple)
+ b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC;
+ else
+ b->encmode = IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT;
+ break;
+ }
+ }
+#endif
+
q = setph2proposal0(iph2, a, b);
if (q == NULL) {
vfree(iph2->sa);
return 0;
}
+/*
+ * return 1 if all of the proposed protocols are tunnel mode.
+ */
+int
+ipsecdoi_tunnelmode(iph2)
+ struct ph2handle *iph2;
+{
+ struct saprop *pp;
+ struct saproto *pr = NULL;
+
+ for (pp = iph2->proposal; pp; pp = pp->next) {
+ for (pr = pp->head; pr; pr = pr->next) {
+ if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TUNNEL &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_RFC &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTUNNEL_DRAFT)
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
/*
* return 1 if all of the proposed protocols are transport mode.
*/
for (pp = iph2->proposal; pp; pp = pp->next) {
for (pr = pp->head; pr; pr = pr->next) {
- if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS)
+ if (pr->encmode != IPSECDOI_ATTR_ENC_MODE_TRNS &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_RFC &&
+ pr->encmode != IPSECDOI_ATTR_ENC_MODE_UDPTRNS_DRAFT)
return 0;
}
}
return 1;
}
+
int
ipsecdoi_get_defaultlifetime()
{
struct ph1handle *iph1;
{
struct ipsecdoi_id_b *id_b;
+ struct sockaddr *sa;
+ caddr_t sa1, sa2;
if (iph1->id_p == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
id_b = (struct ipsecdoi_id_b *)iph1->id_p->v;
- /* In main mode with pre-shared key, only address type can be used. */
+ /* In main mode with pre-shared key, only address type can be used.
+ If NAT Traversal draft 02 being used - allow this. */
if (iph1->etype == ISAKMP_ETYPE_IDENT
- && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY) {
+ && iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY
+ && !natd_hasnat(iph1)) {
if (id_b->type != IPSECDOI_ID_IPV4_ADDR
&& id_b->type != IPSECDOI_ID_IPV6_ADDR) {
plog(LLV_ERROR, LOCATION, NULL,
case IDTYPE_ASN1DN:
ident.v = (caddr_t)(id_b + 1);
ident.l = ident0->l;
- if (eay_cmp_asn1dn(ident0, &ident)) {
- plog(LLV_WARNING, LOCATION, NULL,
- "ID value mismatched.\n");
- if (iph1->rmconf->verify_identifier)
- return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ if (eay_cmp_asn1dn(ident0, &ident))
+ goto err;
+ break;
+ case IDTYPE_ADDRESS:
+ sa = (struct sockaddr *)ident0->v;
+ sa2 = (caddr_t)(id_b + 1);
+ switch (sa->sa_family) {
+ case AF_INET:
+ if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in_addr))
+ goto err;
+
+ sa1 = (caddr_t)&((struct sockaddr_in *)sa)->sin_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in_addr)) != 0)
+ goto err;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (iph1->id_p->l - sizeof(*id_b) != sizeof(struct in6_addr))
+ goto err;
+ sa1 = (caddr_t)&((struct sockaddr_in6 *)sa)->sin6_addr;
+ if (memcmp(sa1, sa2, sizeof(struct in6_addr)) != 0)
+ goto err;
+ break;
+#endif
+ default:
+ goto err;
}
break;
default:
if (memcmp(ident0->v, id_b + 1, ident0->l)) {
+err:
plog(LLV_WARNING, LOCATION, NULL,
"ID value mismatched.\n");
- if (iph1->rmconf->verify_identifier)
+ if (iph1->rmconf->verify_identifier) {
+ vfree(ident0);
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
+ }
}
break;
}
ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
break;
case IDTYPE_KEYID:
+ case IDTYPE_KEYIDUSE:
id_b.type = IPSECDOI_ID_KEY_ID;
ident = getidval(iph1->rmconf->idvtype, iph1->rmconf->idv);
break;
switch (type) {
case IDTYPE_FQDN:
case IDTYPE_USERFQDN:
+ case IDTYPE_KEYIDUSE:
/* length is adjusted since QUOTEDSTRING teminates NULL. */
new = vmalloc(value->l - 1);
if (new == NULL)
vchar_t *ident;
id_b.type = idtype2doi(iph2->sainfo->idvtype);
+ if (id_b.type == 255) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to convert ID type to DOI.\n");
+ return -1;
+ }
id_b.proto_id = 0;
id_b.port = 0;
IPSECDOI_ID_FQDN,
IPSECDOI_ID_USER_FQDN,
IPSECDOI_ID_KEY_ID,
- -1, /* it's type of "address"
+ 255, /* it's type of "address"
* it expands into 4 types by another function. */
IPSECDOI_ID_DER_ASN1_DN,
};
/*
* convert idtype to DOI value.
- * OUT -1 : NG
+ * OUT 255 : NG
* other: converted.
*/
int
{
if (ARRAYLEN(rm_idtype2doi) > idtype)
return rm_idtype2doi[idtype];
- return -1;
+ return 255;
}
int