plog(LLV_WARNING, LOCATION, NULL,
"invalid DH parameter found, use default.\n");
oakley_dhgrp_free(sa->dhgrp);
+ sa->dhgrp=NULL;
}
if (oakley_setdhgroup(sa->dh_group, &sa->dhgrp) == -1) {
sa->dhgrp = NULL;
+ racoon_free(sa);
return NULL;
}
#ifdef HAVE_GSSAPI
if (sa->gssid != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "gss id in new sa '%.*s'\n",
- sa->gssid->l, sa->gssid->v);
+ (int)sa->gssid->l, sa->gssid->v);
if (iph1-> side == INITIATOR) {
if (iph1->rmconf->proposal->gssid != NULL)
iph1->gi_i = vdup(iph1->rmconf->proposal->gssid);
}
if (iph1->gi_i != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "GIi is %.*s\n",
- iph1->gi_i->l, iph1->gi_i->v);
+ (int)iph1->gi_i->l, iph1->gi_i->v);
if (iph1->gi_r != NULL)
plog(LLV_DEBUG, LOCATION, NULL, "GIr is %.*s\n",
- iph1->gi_r->l, iph1->gi_r->v);
+ (int)iph1->gi_r->l, iph1->gi_r->v);
#else
iph1->approval = sa;
#endif
+ if(iph1->approval) {
+ plog(LLV_DEBUG, LOCATION, NULL, "agreed on %s auth.\n",
+ s_oakley_attr_method(iph1->approval->authmethod));
+ }
newsa = get_sabyproppair(p, iph1);
if (newsa == NULL) {
struct isakmp_pl_t *trns = p->trns;
struct isakmpsa sa, *s, *tsap;
int authmethod;
+ int tsap_authmethod;
plog(LLV_DEBUG, LOCATION, NULL,
"prop#=%d, prot-id=%s, spi-size=%d, #trns=%d\n",
for (s = proposal; s != NULL; s = s->next) {
#ifdef ENABLE_HYBRID
authmethod = switch_authmethod(s->authmethod);
+ tsap_authmethod = switch_authmethod(tsap->authmethod);
#else
authmethod = s->authmethod;
+ tsap_authmethod = tsap->authmethod;
#endif
plog(LLV_DEBUG, LOCATION, NULL, "Compared: DB:Peer\n");
plog(LLV_DEBUG, LOCATION, NULL, "(lifetime = %ld:%ld)\n",
tsap->hashtype));
plog(LLV_DEBUG, LOCATION, NULL, "authmethod = %s:%s\n",
s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
- authmethod),
+ s->authmethod),
s_oakley_attr_v(OAKLEY_ATTR_AUTH_METHOD,
tsap->authmethod));
plog(LLV_DEBUG, LOCATION, NULL, "dh_group = %s:%s\n",
* is bigger than mine, it might be accepted.
*/
if(tsap->enctype == s->enctype &&
- tsap->authmethod == authmethod &&
+ (tsap->authmethod == authmethod || tsap_authmethod == authmethod) &&
tsap->hashtype == s->hashtype &&
tsap->dh_group == s->dh_group &&
tsap->encklen == s->encklen) {
}
found:
- if (tsap->dhgrp != NULL)
+ if (tsap->dhgrp != NULL){
oakley_dhgrp_free(tsap->dhgrp);
+ tsap->dhgrp = NULL;
+ }
if ((s = dupisakmpsa(s)) != NULL) {
switch(check_level) {
default:
break;
}
+ // hack to get around cisco rekeys
+ if (tsap->authmethod != authmethod && tsap_authmethod == authmethod) {
+ s->authmethod = tsap->authmethod;
+ }
}
-
return s;
}
}
}
- if (sa.dhgrp != NULL)
+ if (sa.dhgrp != NULL){
oakley_dhgrp_free(sa.dhgrp);
+ sa.dhgrp=NULL;
+ }
}
/*
#ifdef HAVE_GSSAPI
case OAKLEY_ATTR_GSS_ID:
{
- iconv_t cd;
+ int error = -1;
+ iconv_t cd = (iconv_t) -1;
size_t srcleft, dstleft, rv;
__iconv_const char *src;
char *dst;
* compatible with this behavior.
*/
if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
- sa->gssid = vmalloc(len);
+ if ((sa->gssid = vmalloc(len)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate memory\n");
+ goto out;
+ }
memcpy(sa->gssid->v, d + 1, len);
plog(LLV_DEBUG, LOCATION, NULL,
- "received old-style gss id '%.*s' (len %d)\n",
- sa->gssid->l, sa->gssid->v, sa->gssid->l);
- break;
+ "received old-style gss "
+ "id '%.*s' (len %zu)\n",
+ (int)sa->gssid->l, sa->gssid->v,
+ sa->gssid->l);
+ error = 0;
+ goto out;
}
/*
"unable to initialize utf-16le -> latin1 "
"conversion descriptor: %s\n",
strerror(errno));
- break;
+ goto out;
}
- sa->gssid = vmalloc(len / 2);
+ if ((sa->gssid = vmalloc(len / 2)) == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to allocate memory\n");
+ goto out;
+ }
src = (__iconv_const char *)(d + 1);
srcleft = len;
"be represented in latin1\n",
rv, rv == 1 ? "" : "s");
}
- (void) iconv_close(cd);
- vfree(sa->gssid);
- sa->gssid = NULL;
- break;
+ goto out;
}
- (void) iconv_close(cd);
/* XXX dstleft should always be 0; assert it? */
sa->gssid->l = (len / 2) - dstleft;
plog(LLV_DEBUG, LOCATION, NULL,
- "received gss id '%.*s' (len %d)\n",
- sa->gssid->l, sa->gssid->v, sa->gssid->l);
+ "received gss id '%.*s' (len %zu)\n",
+ (int)sa->gssid->l, sa->gssid->v, sa->gssid->l);
+
+ error = 0;
+out:
+ if (cd != (iconv_t)-1)
+ (void)iconv_close(cd);
+
+ if ((error != 0) && (sa->gssid != NULL)) {
+ vfree(sa->gssid);
+ sa->gssid = NULL;
+ }
break;
}
#endif /* HAVE_GSSAPI */
{
struct saproto *sp;
- struct prop_pair *p, *n, *x;
+ struct prop_pair *p, *x;
+ struct prop_pair *n = NULL;
ret = NULL;
goto err; /* XXX */
n = racoon_calloc(1, sizeof(struct prop_pair));
- if (!n) {
+ if (n == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get buffer.\n");
goto err;
vchar_t *sa;
int mode;
{
- struct prop_pair **pair;
+ struct prop_pair **pair = NULL;
int num_p = 0; /* number of proposal for use */
int tlen;
caddr_t bp;
if (sa->l < sizeof(*sab)) {
plog(LLV_ERROR, LOCATION, NULL,
"Invalid SA length = %zu.\n", sa->l);
- return NULL;
+ goto bad;
}
/* check DOI */
if (check_doi(ntohl(sab->doi)) < 0)
- return NULL;
+ goto bad;
/* check SITUATION */
if (check_situation(ntohl(sab->sit)) < 0)
- return NULL;
+ goto bad;
pair = racoon_calloc(1, MAXPROPPAIRLEN * sizeof(*pair));
if (pair == NULL) {
plog(LLV_ERROR, LOCATION, NULL,
"failed to get buffer.\n");
- return NULL;
+ goto bad;
}
memset(pair, 0, sizeof(pair));
pbuf = isakmp_parsewoh(ISAKMP_NPTYPE_P, (struct isakmp_gen *)bp, tlen);
if (pbuf == NULL)
- return NULL;
+ goto bad;
for (pa = (struct isakmp_parse_t *)pbuf->v;
pa->type != ISAKMP_NPTYPE_NONE;
plog(LLV_ERROR, LOCATION, NULL,
"Invalid payload type=%u\n", pa->type);
vfree(pbuf);
- return NULL;
+ goto bad;
}
prop = (struct isakmp_pl_p *)pa->ptr;
plog(LLV_ERROR, LOCATION, NULL,
"invalid proposal with length %d\n", proplen);
vfree(pbuf);
- return NULL;
+ goto bad;
}
/* check Protocol ID */
/* get transform */
if (get_transform(prop, pair, &num_p) < 0) {
vfree(pbuf);
- return NULL;
+ goto bad;
}
}
vfree(pbuf);
if (num_p <= 0) {
plog(LLV_ERROR, LOCATION, NULL,
"no Proposal found.\n");
- return NULL;
+ goto bad;
}
return pair;
+bad:
+ if (pair != NULL)
+ racoon_free(pair);
+ return NULL;
}
/*
struct saprop *pp0;
vchar_t *sa0;
{
- struct prop_pair **pair;
- vchar_t *newsa;
+ struct prop_pair **pair = NULL;
+ vchar_t *newsa = NULL;
int newtlen;
u_int8_t *np_p = NULL;
struct prop_pair *p = NULL;
struct satrns *tr;
int prophlen, trnslen;
caddr_t bp;
+ int error = -1;
/* get proposal pair */
pair = get_proppair(sa0, IPSECDOI_TYPE_PH2);
if (pair == NULL)
- return NULL;
+ goto out;
newtlen = sizeof(struct ipsecdoi_sa_b);
for (pp = pp0; pp; pp = pp->next) {
if (pair[pp->prop_no] == NULL)
- return NULL;
+ goto out;
for (pr = pp->head; pr; pr = pr->next) {
newtlen += (sizeof(struct isakmp_pl_p)
break;
}
if (p == NULL)
- return NULL;
+ goto out;
newtlen += ntohs(p->trns->h.len);
}
newsa = vmalloc(newtlen);
if (newsa == NULL) {
plog(LLV_ERROR, LOCATION, NULL, "failed to get newsa.\n");
- return NULL;
+ goto out;
}
bp = newsa->v;
break;
}
if (p == NULL)
- return NULL;
+ goto out;
trnslen = ntohs(p->trns->h.len);
}
}
+ error = 0;
+out:
+ if (pair != NULL)
+ racoon_free(pair);
+
+ if (error != 0) {
+ if (newsa != NULL) {
+ vfree(newsa);
+ newsa = NULL;
+ }
+ }
+
return newsa;
}
case OAKLEY_ATTR_AUTH_METHOD_RSASIG:
#ifdef ENABLE_HYBRID
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_I:
-#endif
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I:
+#if 0 /* Clashes with OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB */
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I:
+#endif
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
+#endif
case OAKLEY_ATTR_AUTH_METHOD_GSSAPI_KRB:
break;
case OAKLEY_ATTR_AUTH_METHOD_DSSSIG:
#ifdef ENABLE_HYBRID
- case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_RSA_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
+ case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I:
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_I:
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAREV_R:
#endif
case OAKLEY_ATTR_AUTH_METHOD_RSAENC:
case OAKLEY_ATTR_AUTH_METHOD_RSAREV:
plog(LLV_ERROR, LOCATION, NULL,
- "auth method %d isn't supported.\n",
- lorv);
+ "auth method %s isn't supported.\n",
+ s_oakley_attr_method(lorv));
return -1;
default:
plog(LLV_ERROR, LOCATION, NULL,
else
attrlen += sa->gssid->l * 2;
if (buf) {
- plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %d, "
- "val '%.*s'\n", sa->gssid->l, sa->gssid->l,
+ plog(LLV_DEBUG, LOCATION, NULL, "gss id attr: len %zu, "
+ "val '%.*s'\n", sa->gssid->l, (int)sa->gssid->l,
sa->gssid->v);
if (lcconf->gss_id_enc == LC_GSSENC_LATIN1) {
p = isakmp_set_attr_v(p, OAKLEY_ATTR_GSS_ID,
#ifdef __APPLE__
/*
- * return 1 if all of the given protocols are transport mode.
+ * return 1 if all of the given protocols are tunnel mode.
*/
int
ipsecdoi_tunnelmode(iph2)
return 1;
}
+
+/*
+ * return 1 if any of the given protocols are transport mode.
+ */
+int
+ipsecdoi_any_transportmode(pp)
+struct saprop *pp;
+{
+ struct saproto *pr = NULL;
+
+ for (; pp; pp = pp->next) {
+ for (pr = pp->head; pr; pr = pr->next) {
+ 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 1;
+ }
+ }
+
+ return 0;
+}
#endif
/*
return -1; /* XXX */
}
+/*
+ * Check if a subnet id is valid for comparison
+ * with an address id ( address length mask )
+ * and compare them
+ * Return value
+ * = 0 for match
+ * = 1 for mismatch
+ */
+
+int
+ipsecdoi_subnetisaddr_v4( subnet, address )
+ const vchar_t *subnet;
+ const vchar_t *address;
+{
+ struct in_addr *mask;
+
+ if (address->l != sizeof(struct in_addr))
+ return 1;
+
+ if (subnet->l != (sizeof(struct in_addr)*2))
+ return 1;
+
+ mask = (struct in_addr*)(subnet->v + sizeof(struct in_addr));
+
+ if (mask->s_addr!=0xffffffff)
+ return 1;
+
+ return memcmp(subnet->v,address->v,address->l);
+}
+
+#ifdef INET6
+
+int
+ipsecdoi_subnetisaddr_v6( subnet, address )
+ const vchar_t *subnet;
+ const vchar_t *address;
+{
+ struct in6_addr *mask;
+ int i;
+
+ if (address->l != sizeof(struct in6_addr))
+ return 1;
+
+ if (subnet->l != (sizeof(struct in6_addr)*2))
+ return 1;
+
+ mask = (struct in6_addr*)(subnet->v + sizeof(struct in6_addr));
+
+ for (i=0; i<16; i++)
+ if(mask->s6_addr[i]!=0xff)
+ return 1;
+
+ return memcmp(subnet->v,address->v,address->l);
+}
+
+#endif
+
+/*
+ * Check and Compare two IDs
+ * - specify 0 for exact if wildcards are allowed
+ * Return value
+ * = 0 for match
+ * = 1 for misatch
+ * = -1 for integrity error
+ */
+
+int
+ipsecdoi_chkcmpids( idt, ids, exact )
+ const vchar_t *idt; /* id cmp target */
+ const vchar_t *ids; /* id cmp source */
+ int exact;
+{
+ struct ipsecdoi_id_b *id_bt;
+ struct ipsecdoi_id_b *id_bs;
+ vchar_t ident_t;
+ vchar_t ident_s;
+ int result;
+
+ /* handle wildcard IDs */
+
+ if (idt == NULL || ids == NULL)
+ {
+ if( !exact )
+ {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : values matched (ANONYMOUS)\n" );
+ return 0;
+ }
+ else
+ {
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : value mismatch (ANONYMOUS)\n" );
+ return -1;
+ }
+ }
+
+ /* make sure the ids are of the same type */
+
+ id_bt = (struct ipsecdoi_id_b *) idt->v;
+ id_bs = (struct ipsecdoi_id_b *) ids->v;
+
+ ident_t.v = idt->v + sizeof(*id_bt);
+ ident_t.l = idt->l - sizeof(*id_bt);
+ ident_s.v = ids->v + sizeof(*id_bs);
+ ident_s.l = ids->l - sizeof(*id_bs);
+
+ if (id_bs->type != id_bt->type)
+ {
+ /*
+ * special exception for comparing
+ * address to subnet id types when
+ * the netmask is address length
+ */
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)) {
+ result = ipsecdoi_subnetisaddr_v4(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV4_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV4_ADDR)) {
+ result = ipsecdoi_subnetisaddr_v4(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+
+#ifdef INET6
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)) {
+ result = ipsecdoi_subnetisaddr_v6(&ident_t,&ident_s);
+ goto cmpid_result;
+ }
+
+ if ((id_bs->type == IPSECDOI_ID_IPV6_ADDR_SUBNET)&&
+ (id_bt->type == IPSECDOI_ID_IPV6_ADDR)) {
+ result = ipsecdoi_subnetisaddr_v6(&ident_s,&ident_t);
+ goto cmpid_result;
+ }
+#endif
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : id type mismatch %s != %s\n",
+ s_ipsecdoi_ident(id_bs->type),
+ s_ipsecdoi_ident(id_bt->type));
+
+ return 1;
+ }
+
+ if(id_bs->proto_id != id_bt->proto_id){
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : proto_id mismatch %d != %d\n",
+ id_bs->proto_id, id_bt->proto_id);
+
+ return 1;
+ }
+
+ /* compare the ID data. */
+
+ switch (id_bt->type) {
+ case IPSECDOI_ID_DER_ASN1_DN:
+ case IPSECDOI_ID_DER_ASN1_GN:
+ /* compare asn1 ids */
+ result = eay_cmp_asn1dn(&ident_t, &ident_s);
+ goto cmpid_result;
+
+ case IPSECDOI_ID_IPV4_ADDR:
+ /* validate lengths */
+ if ((ident_t.l != sizeof(struct in_addr))||
+ (ident_s.l != sizeof(struct in_addr)))
+ goto cmpid_invalid;
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+ /* validate lengths */
+ if ((ident_t.l != (sizeof(struct in_addr)*2))||
+ (ident_s.l != (sizeof(struct in_addr)*2)))
+ goto cmpid_invalid;
+ break;
+
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ /* validate lengths */
+ if ((ident_t.l != sizeof(struct in6_addr))||
+ (ident_s.l != sizeof(struct in6_addr)))
+ goto cmpid_invalid;
+ break;
+
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+ /* validate lengths */
+ if ((ident_t.l != (sizeof(struct in6_addr)*2))||
+ (ident_s.l != (sizeof(struct in6_addr)*2)))
+ goto cmpid_invalid;
+ break;
+#endif
+ case IPSECDOI_ID_FQDN:
+ case IPSECDOI_ID_USER_FQDN:
+ case IPSECDOI_ID_KEY_ID:
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "Unhandled id type %i specified for comparison\n",
+ id_bt->type);
+ return -1;
+ }
+
+ /* validate matching data and length */
+ if (ident_t.l == ident_s.l)
+ result = memcmp(ident_t.v,ident_s.v,ident_t.l);
+ else
+ result = 1;
+
+cmpid_result:
+
+ /* debug level output */
+ if(loglevel >= LLV_DEBUG) {
+ char *idstrt = ipsecdoi_id2str(idt);
+ char *idstrs = ipsecdoi_id2str(ids);
+
+ if (!result)
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : values matched (%s)\n",
+ s_ipsecdoi_ident(id_bs->type) );
+ else
+ plog(LLV_DEBUG, LOCATION, NULL,
+ "check and compare ids : value mismatch (%s)\n",
+ s_ipsecdoi_ident(id_bs->type));
+
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: \'%s\'\n", idstrt );
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: \'%s\'\n", idstrs );
+
+ racoon_free(idstrs);
+ racoon_free(idstrt);
+ }
+
+ /* return result */
+ if( !result )
+ return 0;
+ else
+ return 1;
+
+cmpid_invalid:
+
+ /* id integrity error */
+ plog(LLV_DEBUG, LOCATION, NULL, "check and compare ids : %s integrity error\n",
+ s_ipsecdoi_ident(id_bs->type));
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid target: length = \'%zu\'\n", ident_t.l );
+ plog(LLV_DEBUG, LOCATION, NULL, "cmpid source: length = \'%zu\'\n", ident_s.l );
+
+ return -1;
+}
+
/*
* check the following:
* - In main mode with pre-shared key, only address type can be used.
}
/* if phase 1 ID payload conformed RFC2407 4.6.2. */
- if (id_b->type == IPSECDOI_ID_IPV4_ADDR || // %%%% BUG_FIX - should be || not &&
+ if (id_b->type == IPSECDOI_ID_IPV4_ADDR ||
id_b->type == IPSECDOI_ID_IPV6_ADDR) {
if (id_b->proto_id == 0 && ntohs(id_b->port) != 0) {
switch (id->idtype) {
case IDTYPE_ASN1DN:
- ident.v = (caddr_t)(id_b + 1);
- ident.l = iph1->id_p->l - 1; /* had ident.l = ident0->l; but why?? */
- /* is the actual packet contents length sometimes wrong? */
+ ident.v = iph1->id_p->v + sizeof(*id_b);
+ ident.l = iph1->id_p->l - sizeof(*id_b);
if (eay_cmp_asn1dn(ident0, &ident) == 0)
goto matched;
break;
set_identifier(vpp, type, value)
vchar_t **vpp, *value;
int type;
+{
+ return set_identifier_qual(vpp, type, value, IDQUAL_UNSPEC);
+}
+
+int
+set_identifier_qual(vpp, type, value, qual)
+ vchar_t **vpp, *value;
+ int type;
+ int qual;
{
vchar_t *new = NULL;
memcpy(new->v, value->v, new->l);
break;
case IDTYPE_KEYID:
- {
- FILE *fp;
- char b[512];
- int tlen, len;
-
- fp = fopen(value->v, "r");
- if (fp == NULL) {
- plog(LLV_ERROR, LOCATION, NULL,
- "can not open %s\n", value->v);
- return -1;
+ /*
+ * If no qualifier is specified: IDQUAL_UNSPEC. It means
+ * to use a file for backward compatibility sake.
+ */
+ switch(qual) {
+ case IDQUAL_FILE:
+ case IDQUAL_UNSPEC: {
+ FILE *fp;
+ char b[512];
+ int tlen, len;
+
+ fp = fopen(value->v, "r");
+ if (fp == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "can not open %s\n", value->v);
+ return -1;
+ }
+ tlen = 0;
+ while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
+ new = vrealloc(new, tlen + len);
+ if (!new) {
+ fclose(fp);
+ return -1;
+ }
+ memcpy(new->v + tlen, b, len);
+ tlen += len;
+ }
+ fclose(fp);
+ break;
}
- tlen = 0;
- while ((len = fread(b, 1, sizeof(b), fp)) != 0) {
- new = vrealloc(new, tlen + len);
- if (!new) {
- fclose(fp);
+
+ case IDQUAL_TAG:
+ new = vmalloc(value->l - 1);
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "can not allocate memory");
return -1;
}
- memcpy(new->v + tlen, b, len);
- tlen += len;
+ memcpy(new->v, value->v, new->l);
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unknown qualifier");
+ return -1;
}
break;
- }
- case IDTYPE_ADDRESS:
- {
+
+ case IDTYPE_ADDRESS: {
struct sockaddr *sa;
/* length is adjusted since QUOTEDSTRING teminates NULL. */
}
new = vmalloc(sysdep_sa_len(sa));
- if (new == NULL)
+ if (new == NULL) {
+ racoon_free(sa);
return -1;
+ }
memcpy(new->v, sa, new->l);
+ racoon_free(sa);
break;
}
case IDTYPE_ASN1DN:
switch (saddr->sa_family) {
case AF_INET:
len1 = sizeof(struct in_addr);
- if (
-#if 0
- prefixlen == ~0
-#else
- prefixlen == (sizeof(struct in_addr) << 3)
-#endif
- ) {
+ if (prefixlen == (sizeof(struct in_addr) << 3)) {
type = IPSECDOI_ID_IPV4_ADDR;
len2 = 0;
} else {
#ifdef INET6
case AF_INET6:
len1 = sizeof(struct in6_addr);
- if (
-#if 0
- prefixlen == ~0
-#else
- prefixlen == (sizeof(struct in6_addr) << 3)
-#endif
- ) {
+ if (prefixlen == (sizeof(struct in6_addr) << 3)) {
type = IPSECDOI_ID_IPV6_ADDR;
len2 = 0;
} else {
return new;
}
+vchar_t *
+ipsecdoi_sockrange2id(laddr, haddr, ul_proto)
+ struct sockaddr *laddr, *haddr;
+ u_int ul_proto;
+{
+ vchar_t *new;
+ int type, len1, len2;
+ u_short port;
+
+ if (laddr->sa_family != haddr->sa_family) {
+ plog(LLV_ERROR, LOCATION, NULL, "Address family mismatch\n");
+ return NULL;
+ }
+
+ switch (laddr->sa_family) {
+ case AF_INET:
+ type = IPSECDOI_ID_IPV4_ADDR_RANGE;
+ len1 = sizeof(struct in_addr);
+ len2 = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ type = IPSECDOI_ID_IPV6_ADDR_RANGE;
+ len1 = sizeof(struct in6_addr);
+ len2 = sizeof(struct in6_addr);
+ break;
+#endif
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "invalid family: %d.\n", laddr->sa_family);
+ return NULL;
+ }
+
+ /* get ID buffer */
+ new = vmalloc(sizeof(struct ipsecdoi_id_b) + len1 + len2);
+ if (new == NULL) {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "failed to get ID buffer.\n");
+ return NULL;
+ }
+
+ memset(new->v, 0, new->l);
+ /* set the part of header. */
+ ((struct ipsecdoi_id_b *)new->v)->type = type;
+
+ /* set ul_proto and port */
+ /*
+ * NOTE: we use both IPSEC_ULPROTO_ANY and IPSEC_PORT_ANY as wild card
+ * because 0 means port number of 0. Instead of 0, we use IPSEC_*_ANY.
+ */
+ ((struct ipsecdoi_id_b *)new->v)->proto_id =
+ ul_proto == IPSEC_ULPROTO_ANY ? 0 : ul_proto;
+ port = ((struct sockaddr_in *)(laddr))->sin_port;
+ ((struct ipsecdoi_id_b *)new->v)->port =
+ port == IPSEC_PORT_ANY ? 0 : port;
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b),
+ (caddr_t)&((struct sockaddr_in *)(laddr))->sin_addr,
+ len1);
+ memcpy(new->v + sizeof(struct ipsecdoi_id_b) + len1,
+ (caddr_t)&((struct sockaddr_in *)haddr)->sin_addr,
+ len2);
+ return new;
+}
+
+
/*
* create sockaddr structure from ID payload (buf).
* buffers (saddr, prefixlen, ul_proto) must be allocated.
+ alen;
for (; *p == 0xff; p++) {
+ plen += 8;
if (plen >= max)
break;
- plen += 8;
}
if (plen < max) {
/*
* make printable string from ID payload except of general header.
*/
-const char *
+char *
ipsecdoi_id2str(id)
const vchar_t *id;
{
- static char buf[256];
+#define BUFLEN 512
+ char * ret = NULL;
+ int len = 0;
+ char *dat;
+ static char buf[BUFLEN];
+ struct ipsecdoi_id_b *id_b = (struct ipsecdoi_id_b *)id->v;
+ struct sockaddr_storage saddr;
+ u_int plen = 0;
+
+ bzero(&saddr, sizeof(saddr));
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+#ifndef __linux__
+ ((struct sockaddr *)&saddr)->sa_len = sizeof(struct sockaddr_in);
+#endif
+ ((struct sockaddr *)&saddr)->sa_family = AF_INET;
+ ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
+ memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
+ id->v + sizeof(*id_b), sizeof(struct in_addr));
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+#ifndef __linux__
+ ((struct sockaddr *)&saddr)->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ ((struct sockaddr *)&saddr)->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
+ memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
+ id->v + sizeof(*id_b), sizeof(struct in6_addr));
+ break;
+#endif
+ }
+
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR:
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR:
+#endif
+ len = snprintf( buf, sizeof(buf), "%s", saddrwop2str((struct sockaddr *)&saddr));
+ break;
- /* XXX */
- buf[0] = '\0';
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+#endif
+ {
+ u_char *p;
+ u_int max;
+ int alen = sizeof(struct in_addr);
- return buf;
+ switch (id_b->type) {
+ case IPSECDOI_ID_IPV4_ADDR_SUBNET:
+ alen = sizeof(struct in_addr);
+ break;
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_SUBNET:
+ alen = sizeof(struct in6_addr);
+ break;
+#endif
+ }
+
+ /* sanity check */
+ if (id->l < alen) {
+ len = 0;
+ break;
+ }
+
+ /* get subnet mask length */
+ plen = 0;
+ max = alen <<3;
+
+ p = (unsigned char *) id->v
+ + sizeof(struct ipsecdoi_id_b)
+ + alen;
+
+ for (; *p == 0xff; p++) {
+ plen += 8;
+ if (plen >= max)
+ break;
+ }
+
+ if (plen < max) {
+ u_int l = 0;
+ u_char b = ~(*p);
+
+ while (b) {
+ b >>= 1;
+ l++;
+ }
+
+ l = 8 - l;
+ plen += l;
+ }
+
+ len = snprintf( buf, sizeof(buf), "%s/%i", saddrwop2str((struct sockaddr *)&saddr), plen);
+ }
+ break;
+
+ case IPSECDOI_ID_IPV4_ADDR_RANGE:
+
+ len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr));
+
+#ifndef __linux__
+ ((struct sockaddr *)&saddr)->sa_len = sizeof(struct sockaddr_in);
+#endif
+ ((struct sockaddr *)&saddr)->sa_family = AF_INET;
+ ((struct sockaddr_in *)&saddr)->sin_port = IPSEC_PORT_ANY;
+ memcpy(&((struct sockaddr_in *)&saddr)->sin_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in_addr),
+ sizeof(struct in_addr));
+
+ if (len >= 0) {
+ len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
+ }
+
+ break;
+
+#ifdef INET6
+ case IPSECDOI_ID_IPV6_ADDR_RANGE:
+
+ len = snprintf( buf, sizeof(buf), "%s-", saddrwop2str((struct sockaddr *)&saddr));
+
+#ifndef __linux__
+ ((struct sockaddr *)&saddr)->sa_len = sizeof(struct sockaddr_in6);
+#endif
+ ((struct sockaddr *)&saddr)->sa_family = AF_INET6;
+ ((struct sockaddr_in6 *)&saddr)->sin6_port = IPSEC_PORT_ANY;
+ memcpy(&((struct sockaddr_in6 *)&saddr)->sin6_addr,
+ id->v + sizeof(*id_b) + sizeof(struct in6_addr),
+ sizeof(struct in6_addr));
+
+ if (len >= 0) {
+ len += snprintf( buf + len, sizeof(buf) - len, "%s", saddrwop2str((struct sockaddr *)&saddr));
+ }
+
+ break;
+#endif
+
+ case IPSECDOI_ID_FQDN:
+ case IPSECDOI_ID_USER_FQDN:
+ len = id->l - sizeof(*id_b);
+ if (len > BUFLEN)
+ len = BUFLEN;
+ memcpy(buf, id->v + sizeof(*id_b), len);
+ break;
+
+ case IPSECDOI_ID_DER_ASN1_DN:
+ case IPSECDOI_ID_DER_ASN1_GN:
+ {
+ X509_NAME *xn = NULL;
+
+ dat = id->v + sizeof(*id_b);
+ len = id->l - sizeof(*id_b);
+
+ if (d2i_X509_NAME(&xn, (void*) &dat, len) != NULL) {
+ BIO *bio = BIO_new(BIO_s_mem());
+ X509_NAME_print_ex(bio, xn, 0, 0);
+ len = BIO_get_mem_data(bio, &dat);
+ if (len > BUFLEN)
+ len = BUFLEN;
+ memcpy(buf,dat,len);
+ BIO_free(bio);
+ X509_NAME_free(xn);
+ } else {
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unable to extract asn1dn from id\n");
+
+ len = snprintf(buf, sizeof(buf), "<ASN1-DN>");
+ }
+
+ break;
+ }
+
+ /* currently unhandled id types */
+ case IPSECDOI_ID_KEY_ID:
+ len = snprintf( buf, sizeof(buf), "<KEY-ID>");
+ break;
+
+ default:
+ plog(LLV_ERROR, LOCATION, NULL,
+ "unknown ID type %d\n", id_b->type);
+ }
+
+ if (!len)
+ len = snprintf( buf, sizeof(buf), "<?>");
+
+ ret = racoon_malloc(len+1);
+ if (ret != NULL) {
+ memcpy(ret,buf,len);
+ ret[len]=0;
+ }
+
+ return ret;
}
/*
255, /* IDTYPE_ADDRESS, 4
* it expands into 4 types by another function. */
IPSECDOI_ID_DER_ASN1_DN, /* IDTYPE_ASN1DN, 5 */
-#ifdef ENABLE_HYBRID
- 255, /* IDTYPE_LOGIN, 6 */
-#endif
};
/*
case OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_R:
authmethod = OAKLEY_ATTR_AUTH_METHOD_HYBRID_DSS_I;
break;
- /* Those are not implemented */
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_R:
authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_PSKEY_I;
break;
- case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
- authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
- break;
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_R:
authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSASIG_I;
break;
+ /* Those are not implemented */
+ case OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_R:
+ authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_DSSSIG_I;
+ break;
case OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_R:
authmethod = OAKLEY_ATTR_AUTH_METHOD_XAUTH_RSAENC_I;
break;