dnskey.c dnskey.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
-id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
+myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
out:
- if (status != SUCCESS)
+ if (status == SUCCESS)
+ {
+ alg_info_esp->ref_cnt = 1;
+ return alg_info_esp;
+ }
+ else
{
free(alg_info_esp);
- alg_info_esp = NULL;
+ return NULL;
}
- return alg_info_esp;
}
struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
zero(alg_info_ike);
alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
- if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) != SUCCESS)
+ if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
+ {
+ alg_info_ike->ref_cnt = 1;
+ return alg_info_ike;
+ }
+ else
{
free(alg_info_ike);
return NULL;
}
- return alg_info_ike;
}
/*
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "certs.h"
#include "ac.h"
#include "crl.h"
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "certs.h"
#include "whack.h"
#include "builder.h"
}
/* release of a certificate decreases the count by one
- " the certificate is freed when the counter reaches zero
+ * the certificate is freed when the counter reaches zero
*/
-void
-release_cert(cert_t cert)
+void release_cert(cert_t cert)
{
switch (cert.type)
{
}
}
-/*
+/**
* list all X.509 and OpenPGP end certificates
*/
-void
-list_certs(bool utc)
+void list_certs(bool utc)
{
list_x509_end_certs(utc);
list_pgp_end_certs(utc);
#include "constants.h"
#include "defs.h"
-#include "id.h"
+#include "myid.h"
#include "x509.h"
#include "ca.h"
#include "crl.h"
static connection_t *unoriented_connections = NULL;
-/* check to see that Ids of peers match */
+/**
+ * Check if an id was instantiated by assigning to it the current IP address
+ */
+bool his_id_was_instantiated(const connection_t *c)
+{
+ if (c->kind != CK_INSTANCE)
+ {
+ return FALSE;
+ }
+ if (id_is_ipaddr(c->spd.that.id))
+ {
+ identification_t *host;
+ bool equal;
+
+ host = identification_create_from_sockaddr((sockaddr_t*)&c->spd.that.host_addr);
+ equal = host->equals(host, c->spd.that.id);
+ host->destroy(host);
+ return equal;
+ }
+ else
+ {
+ return TRUE;
+ }
+}
+
+/**
+ * Check to see that IDs of peers match
+ */
bool same_peer_ids(const connection_t *c, const connection_t *d,
- const struct id *his_id)
+ identification_t *his_id)
{
- return same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(his_id == NULL? &c->spd.that.id : his_id, &d->spd.that.id);
+ return d->spd.this.id->equals(d->spd.this.id, c->spd.this.id) &&
+ d->spd.that.id->equals(d->spd.that.id,
+ his_id ? his_id : c->spd.that.id);
}
static struct host_pair *find_host_pair(const ip_address *myaddr,
if (sameaddr(&p->me.addr, myaddr) && p->me.port == myport
&& sameaddr(&p->him.addr, hisaddr) && p->him.port == hisport)
{
- if (prev != NULL)
+ if (prev)
{
prev->next = p->next; /* remove p from list */
p->next = host_pairs; /* and stick it on front */
if (streq(p->name, nm)
&& (!strict || p->kind != CK_INSTANCE))
{
- if (prev != NULL)
+ if (prev)
{
prev->ac_next = p->ac_next; /* remove p from list */
p->ac_next = connections; /* and stick it on front */
cur_debugging = old_cur_debugging;
#endif
free(c->name);
- free_id_content(&c->spd.this.id);
- free(c->spd.this.updown);
+ DESTROY_IF(c->spd.this.id);
DESTROY_IF(c->spd.this.ca);
DESTROY_IF(c->spd.this.groups);
- free_id_content(&c->spd.that.id);
- free(c->spd.that.updown);
+ free(c->spd.this.updown);
+ DESTROY_IF(c->spd.that.id);
DESTROY_IF(c->spd.that.ca);
DESTROY_IF(c->spd.that.groups);
+ free(c->spd.that.updown);
if (c->requested_ca)
{
c->requested_ca->destroy_offset(c->requested_ca,
void delete_every_connection(void)
{
- while (connections != NULL)
+ while (connections)
+ {
delete_connection(connections, TRUE);
+ }
}
void release_dead_interfaces(void)
unoriented_connections = NULL;
- while (c != NULL)
+ while (c)
{
connection_t *nxt = c->hp_next;
connection_t *c = hp->connections;
hp->connections = NULL;
- while (c != NULL)
+ while (c)
{
connection_t *nxt = c->hp_next;
static err_t default_end(struct end *e, ip_address *dflt_nexthop)
{
err_t ugh = NULL;
- const struct af_info *afi = aftoinfo(addrtypeof(&e->host_addr));
+ int af = addrtypeof(&e->host_addr);
- if (afi == NULL)
+ if (af != AF_INET && af != AF_INET6)
+ {
return "unknown address family in default_end";
+ }
/* default ID to IP (but only if not NO_IP -- WildCard) */
- if (e->id.kind == ID_ANY && !isanyaddr(&e->host_addr))
+ if (e->id->get_type(e->id) == ID_ANY && !isanyaddr(&e->host_addr))
{
- e->id.kind = afi->id_addr;
- e->id.ip_addr = e->host_addr;
+ e->id->destroy(e->id);
+ e->id = identification_create_from_sockaddr((sockaddr_t*)&e->host_addr);
e->has_id_wildcards = FALSE;
}
/* default nexthop to other side */
if (isanyaddr(&e->host_nexthop))
+ {
e->host_nexthop = *dflt_nexthop;
+ }
/* default client to subnet containing only self
* XXX This may mean that the client's address family doesn't match
* tunnel_addr_family.
*/
if (!e->has_client)
+ {
ugh = addrtosubnet(&e->host_addr, &e->client);
-
+ }
return ugh;
}
snprintf(protoport, sizeof(protoport), ":%u/%u", this->protocol
, this->port);
- /* id, if different from host */
- host_id[0] = '\0';
- if (this->id.kind == ID_MYID)
- {
- strcpy(host_id, "[%myid]");
- }
- else if (!(this->id.kind == ID_ANY
- || (id_is_ipaddr(&this->id) && sameaddr(&this->id.ip_addr, &this->host_addr))))
- {
- int len = idtoa(&this->id, host_id+1, sizeof(host_id)-2);
-
- host_id[0] = '[';
- strcpy(&host_id[len < 0? (ptrdiff_t)sizeof(host_id)-2 : 1 + len], "]");
- }
+ /* id */
+ snprintf(host_id, sizeof(host_id), "[%Y]", this->id);
/* [---hop] */
hop[0] = '\0';
hop_sep = "";
- if (that != NULL && !sameaddr(&this->host_nexthop, &that->host_addr))
+ if (that && !sameaddr(&this->host_nexthop, &that->host_addr))
{
addrtot(&this->host_nexthop, 0, hop, sizeof(hop));
hop_sep = "---";
static void unshare_connection_strings(connection_t *c)
{
c->name = clone_str(c->name);
-
- unshare_id_content(&c->spd.this.id);
+ c->spd.this.id = c->spd.this.id->clone(c->spd.this.id);
c->spd.this.updown = clone_str(c->spd.this.updown);
scx_share(c->spd.this.sc);
share_cert(c->spd.this.cert);
{
c->spd.this.ca = c->spd.this.ca->clone(c->spd.this.ca);
}
- unshare_id_content(&c->spd.that.id);
+ if (c->spd.this.groups)
+ {
+ c->spd.this.groups = c->spd.this.groups->get_ref(c->spd.this.groups);
+ }
+ c->spd.that.id = c->spd.that.id->clone(c->spd.that.id);
c->spd.that.updown = clone_str(c->spd.that.updown);
scx_share(c->spd.that.sc);
share_cert(c->spd.that.cert);
{
c->spd.that.ca = c->spd.that.ca->clone(c->spd.that.ca);
}
+ if (c->spd.that.groups)
+ {
+ c->spd.that.groups = c->spd.that.groups->get_ref(c->spd.that.groups);
+ }
/* increment references to algo's */
alg_info_addref((struct alg_info *)c->alg_info_esp);
/* initialize smartcard info record */
dst->sc = NULL;
- if (filename != NULL)
+ if (filename)
{
if (scx_on_smartcard(filename))
{
switch (cert.type)
{
case CERT_PGP:
- select_pgpcert_id(cert.u.pgp, &dst->id);
+ dst->id = select_pgpcert_id(cert.u.pgp, dst->id);
if (cached_cert)
+ {
dst->cert = cert;
+ }
else
{
valid_until = cert.u.pgp->until;
}
break;
case CERT_X509_SIGNATURE:
- select_x509cert_id(cert.u.x509, &dst->id);
+ dst->id = select_x509cert_id(cert.u.x509, dst->id);
if (cached_cert)
{
}
/* cache the certificate that was last retrieved from the smartcard */
- if (dst->sc != NULL)
+ if (dst->sc)
{
if (!same_cert(&dst->sc->last_cert, &dst->cert))
{
time(&dst->sc->last_load);
}
}
+ scx_share(dst->sc);
+ share_cert(dst->cert);
}
static bool extract_end(struct end *dst, const whack_end_t *src,
{
bool same_ca = FALSE;
- /* decode id, if any */
- if (src->id == NULL)
- {
- dst->id.kind = ID_ANY;
- }
- else
- {
- err_t ugh = atoid(src->id, &dst->id, TRUE);
-
- if (ugh != NULL)
- {
- loglog(RC_BADID, "bad %s --id: %s (ignored)", which, ugh);
- dst->id = empty_id; /* ignore bad one */
- }
- }
-
+ dst->id = identification_create_from_string(src->id);
dst->ca = NULL;
/* decode CA distinguished name, if any */
load_end_certificate(src->cert, dst);
/* does id has wildcards? */
- dst->has_id_wildcards = id_count_wildcards(&dst->id) > 0;
+ dst->has_id_wildcards = dst->id->contains_wildcards(dst->id);
/* decode group attributes, if any */
if (src->groups)
dst->hostaccess = src->hostaccess;
dst->allow_any = src->allow_any;
dst->sendcert = src->sendcert;
- dst->updown = src->updown;
+ dst->updown = clone_str(src->updown);
dst->host_port = src->host_port;
/* if host sourceip is defined but no client is present
{
err_t ugh = addrtosubnet(&dst->host_srcip, &dst->client);
- if (ugh != NULL)
+ if (ugh)
+ {
plog("could not assign host sourceip to client subnet");
+ }
else
+ {
dst->has_client = TRUE;
+ }
}
return same_ca;
}
connection_t *c = malloc_thing(connection_t);
zero(c);
- c->name = wm->name;
+ c->name = clone_str(wm->name);
c->ikev1 = wm->ikev1;
c->policy = wm->policy;
DBG(DBG_CONTROL,
DBG_log("from whack: got --esp=%s", wm->esp ? wm->esp: "NULL")
)
- c->alg_info_esp= alg_info_esp_create_from_str(wm->esp? wm->esp : "");
+ c->alg_info_esp = alg_info_esp_create_from_str(wm->esp? wm->esp : "");
DBG(DBG_CRYPT|DBG_CONTROL,
static char buf[BUF_LEN]="<NULL>";
same_rightca = extract_end(&c->spd.that, &wm->right, "right");
if (same_rightca)
- c->spd.that.ca = c->spd.this.ca;
+ {
+ c->spd.that.ca = c->spd.this.ca->clone(c->spd.this.ca);
+ }
else if (same_leftca)
- c->spd.this.ca = c->spd.that.ca;
+ {
+ c->spd.this.ca = c->spd.that.ca->clone(c->spd.that.ca);
+ }
default_end(&c->spd.this, &c->spd.that.host_addr);
default_end(&c->spd.that, &c->spd.this.host_addr);
c->spd.that.has_client = TRUE;
}
- unshare_connection_strings(c);
(void)orient(c);
if (c->ikev1)
+ {
connect_to_host_pair(c);
+ }
/* log all about this connection */
plog("added connection description \"%s\"", c->name);
DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
+ char topo[BUF_LEN];
(void) format_connection(topo, sizeof(topo), c, &c->spd);
*
* Note that instantiate can only deal with a single SPD/eroute.
*/
-static connection_t *instantiate(connection_t *c,
- const ip_address *him, u_int16_t his_port,
- const struct id *his_id)
+static connection_t *instantiate(connection_t *c, const ip_address *him,
+ u_int16_t his_port, identification_t *his_id)
{
connection_t *d;
- int wildcards;
passert(c->kind == CK_TEMPLATE);
passert(c->spd.next == NULL);
d = clone_thing(*c);
d->spd.that.allow_any = FALSE;
- if (his_id != NULL)
+ if (his_id)
{
- passert(match_id(his_id, &d->spd.that.id, &wildcards));
- d->spd.that.id = *his_id;
+ d->spd.that.id = his_id;
d->spd.that.has_id_wildcards = FALSE;
}
unshare_connection_strings(d);
connection_t *rw_instantiate(connection_t *c, const ip_address *him,
u_int16_t his_port, const ip_subnet *his_net,
- const struct id *his_id)
+ identification_t *his_id)
{
connection_t *d = instantiate(c, him, his_port, his_id);
}
connection_t *oppo_instantiate(connection_t *c, const ip_address *him,
- const struct id *his_id, struct gw_info *gw,
+ identification_t *his_id, struct gw_info *gw,
const ip_address *our_client USED_BY_DEBUG,
const ip_address *peer_client)
{
d->instance_initiation_ok = TRUE;
DBG(DBG_CONTROL,
- char topo[CONNECTION_BUF];
+ char topo[BUF_LEN];
(void) format_connection(topo, sizeof(topo), d, &d->spd);
DBG_log("instantiated \"%s\": %s", d->name, topo);
void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF])
{
if (pp == BOTTOM_PRIO)
+ {
snprintf(buf, POLICY_PRIO_BUF, "0");
+ }
else
+ {
snprintf(buf, POLICY_PRIO_BUF, "%lu,%lu"
, pp>>16, (pp & ~(~(policy_prio_t)0 << 16)) >> 8);
+ }
}
/* Format any information needed to identify an instance of a connection.
}
}
- if (best!= NULL && NEVER_NEGOTIATE(best->policy))
+ if (best && NEVER_NEGOTIATE(best->policy))
+ {
best = NULL;
-
- if (srp != NULL && best != NULL)
+ }
+ if (srp && best)
+ {
*srp = best_sr;
+ }
#ifdef DEBUG
if (DBGP(DBG_CONTROL))
addrtot(our_client, 0, ocb, sizeof(ocb));
addrtot(peer_client, 0, pcb, sizeof(pcb));
- passert(!isanyaddr(our_client) && !isanyaddr(peer_client));
-
- /* We don't know his ID yet, so gw id must be an ipaddr */
- passert(gw->key != NULL);
- passert(id_is_ipaddr(&gw->gw_id));
-
/* for each of our addresses... */
for (p = interfaces; p != NULL; p = p->next)
{
}
}
- if (best == NULL
- || NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY
- || best->kind != CK_TEMPLATE)
+ if (best == NULL || NEVER_NEGOTIATE(best->policy) ||
+ (best->policy & POLICY_OPPO) == LEMPTY || best->kind != CK_TEMPLATE)
+ {
return NULL;
+ }
else
- return oppo_instantiate(best, &gw->gw_id.ip_addr, NULL, gw
- , our_client, peer_client);
+ {
+ chunk_t encoding = gw->gw_id->get_encoding(gw->gw_id);
+ id_type_t type = gw->gw_id->get_type(gw->gw_id);
+ ip_address ip_addr;
+
+ initaddr(encoding.ptr, encoding.len,
+ (type == ID_IPV4_ADDR) ? AF_INET : AF_INET6, &ip_addr);
+
+ return oppo_instantiate(best, &ip_addr, NULL, gw, our_client, peer_client);
+ }
}
bool orient(connection_t *c)
{
connection_t *c = con_by_name(name, TRUE);
- if (c != NULL && c->ikev1)
+ if (c && c->ikev1)
{
set_cur_connection(c);
if (!oriented(*c))
else
{
/* do we have to prompt for a PIN code? */
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid && whackfd != NULL_FD)
+ if (c->spd.this.sc && !c->spd.this.sc->valid && whackfd != NULL_FD)
{
scx_get_pin(c->spd.this.sc, whackfd);
}
- if (c->spd.this.sc != NULL && !c->spd.this.sc->valid)
+ if (c->spd.this.sc && !c->spd.this.sc->valid)
{
loglog(RC_NOVALIDPIN, "cannot initiate connection without valid PIN");
}
if (c->spd.that.allow_any)
{
- c = instantiate(c, &c->spd.that.host_addr, c->spd.that.host_port
- , &c->spd.that.id);
+ c = instantiate(c, &c->spd.that.host_addr,
+ c->spd.that.host_port, c->spd.that.id);
}
/* We will only request an IPsec SA if policy isn't empty
, "Can't Opportunistically initiate for %s to %s: %s"
, ocb, pcb, ugh);
- if (c != NULL && c->policy_next != NULL)
+ if (c && c->policy_next)
{
/* there is some policy that comes afterwards */
struct spd_route *shunt_spd;
#ifdef DEBUG
/* if we're going to ignore the error, at least note it in debugging log */
- if (cr->b.failure_ok && ugh != NULL)
+ if (cr->b.failure_ok && ugh)
{
DBG(DBG_CONTROL | DBG_DNS,
{
}
#endif
- if (!cr->b.failure_ok && ugh != NULL)
+ if (!cr->b.failure_ok && ugh)
{
c = find_connection_for_clients(NULL, &cr->b.our_client, &cr->b.peer_client
, cr->b.transport_proto);
}
}
}
- if (ugh != NULL)
+ if (ugh)
+ {
myid_state = old_myid_state;
+ }
return ugh;
}
#endif /* USE_KEYRR */
{
ugh = "we don't know our own RSA key";
}
- else if (!same_id(&ac->id, &c->spd.this.id))
+ else if (!ac->id->equals(ac->id, c->spd.this.id))
{
ugh = "our ID changed underfoot";
}
}
}
}
- if (ugh != NULL)
+ if (ugh)
{
myid_state = old_myid_state;
}
char mycredentialstr[BUF_LEN];
char cib[CONN_INST_BUF];
- DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s"
- , c->name
- , (fmt_conn_instance(c, cib), cib)));
-
-
- idtoa(&sr->this.id, mycredentialstr, sizeof(mycredentialstr));
-
- passert(c->policy & POLICY_OPPO); /* can't initiate Road Warrior connections */
+ DBG(DBG_CONTROL, DBG_log("creating new instance from \"%s\"%s",
+ c->name, (fmt_conn_instance(c, cib), cib)));
+ snprintf(mycredentialstr, BUF_LEN, "%Y", sr->this.id);
/* handle any DNS answer; select next step */
-
switch (b->step)
{
case fos_start:
case fos_myid_ip_txt: /* TXT for our default IP address as %myid */
ugh = check_txt_recs(MYID_IP, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our IP (%Y:TXT) as identity: %s",
+ myids[MYID_IP], ugh));
if (!logged_myid_ip_txt_warning)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:TXT) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our IP (%Y:TXT) as identity: %s",
+ myids[MYID_IP], ugh);
logged_myid_ip_txt_warning = TRUE;
}
/* we can use our IP as OE identity for initiation */
if (!logged_myid_ip_txt_warning)
{
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:TXT) as identity!"
- , myid_str[MYID_IP]);
+ loglog(RC_LOG_SERIOUS,
+ "using our IP (%Y:TXT) as identity!",
+ myids[MYID_IP]);
logged_myid_ip_txt_warning = TRUE;
}
case fos_myid_hostname_txt: /* TXT for our hostname as %myid */
ugh = check_txt_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* cannot use our hostname as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our hostname (%Y:TXT) as identity: %s",
+ myids[MYID_HOSTNAME], ugh));
if (!logged_myid_fqdn_txt_warning)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:TXT) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our hostname (%Y:TXT) as identity: %s",
+ myids[MYID_HOSTNAME], ugh);
logged_myid_fqdn_txt_warning = TRUE;
}
#ifdef USE_KEYRR
/* we can use our hostname as OE identity for initiation */
if (!logged_myid_fqdn_txt_warning)
{
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:TXT) as identity!"
- , myid_str[MYID_HOSTNAME]);
+ loglog(RC_LOG_SERIOUS,
+ "using our hostname (%Y:TXT) as identity!",
+ myids[MYID_HOSTNAME]);
logged_myid_fqdn_txt_warning = TRUE;
}
next_step = fos_our_client;
#ifdef USE_KEYRR
case fos_myid_ip_key: /* KEY for our default IP address as %myid */
ugh = check_key_recs(MYID_IP, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our IP (%Y:KEY) as identity: %s",
+ myids[MYID_IP], ugh));
if (!logged_myid_ip_key_warning)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our IP (%s:KEY) as identity: %s"
- , myid_str[MYID_IP]
- , ugh);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our IP (%Y:KEY) as identity: %s",
+ myids[MYID_IP], ugh);
logged_myid_ip_key_warning = TRUE;
}
/* we can use our IP as OE identity for initiation */
if (!logged_myid_ip_key_warning)
{
- loglog(RC_LOG_SERIOUS
- , "using our IP (%s:KEY) as identity!"
- , myid_str[MYID_IP]);
+ loglog(RC_LOG_SERIOUS,
+ "using our IP (%Y:KEY) as identity!",
+ myids[MYID_IP]);
logged_myid_ip_key_warning = TRUE;
}
next_step = fos_our_client;
case fos_myid_hostname_key: /* KEY for our hostname as %myid */
ugh = check_key_recs(MYID_HOSTNAME, c, ac);
- if (ugh != NULL)
+ if (ugh)
{
/* cannot use our IP as OE identitiy for initiation */
- DBG(DBG_OPPO, DBG_log("can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh));
+ DBG(DBG_OPPO,
+ DBG_log("can not use our hostname (%Y:KEY) as identity: %s",
+ myids[MYID_HOSTNAME], ugh));
if (!logged_myid_fqdn_key_warning)
{
- loglog(RC_LOG_SERIOUS
- , "can not use our hostname (%s:KEY) as identity: %s"
- , myid_str[MYID_HOSTNAME]
- , ugh);
+ loglog(RC_LOG_SERIOUS,
+ "can not use our hostname (%Y:KEY) as identity: %s",
+ myids[MYID_HOSTNAME], ugh);
logged_myid_fqdn_key_warning = TRUE;
}
-
next_step = fos_myid_hostname_key;
ugh = NULL; /* failure can be recovered from */
}
/* we can use our IP as OE identity for initiation */
if (!logged_myid_fqdn_key_warning)
{
- loglog(RC_LOG_SERIOUS
- , "using our hostname (%s:KEY) as identity!"
- , myid_str[MYID_HOSTNAME]);
+ loglog(RC_LOG_SERIOUS,
+ "using our hostname (%Y:KEY) as identity!",
+ myids[MYID_HOSTNAME]);
logged_myid_fqdn_key_warning = TRUE;
}
next_step = fos_our_client;
next_step = fos_his_client; /* normal situation */
- passert(sr != NULL);
-
if (private == NULL)
{
ugh = "we don't know our own RSA key";
/* this wasn't true when we started -- bail */
ugh = "our IP address changed underfoot";
}
- else if (!same_id(&ac->sgw_id, &sr->this.id))
+ else if (!ac->sgw_id->equals(ac->sgw_id, sr->this.id))
{
/* this wasn't true when we started -- bail */
ugh = "our ID changed underfoot";
ugh = "no TXT RR for our client delegates us";
for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
ugh = "TXT RR for our client has wrong key";
/* If there is a key from the TXT record,
* we count it as a win if we match the key.
{
ugh = "we don't know our own RSA key";
}
- else if (!same_id(&ac->id, &c->spd.this.id))
+ else if (!ac->id->equals(ac->id, c->spd.this.id))
{
ugh = "our ID changed underfoot";
}
ugh = "no TXT RR for us";
for (gwp = ac->gateways_from_dns; gwp != NULL; gwp = gwp->next)
{
- passert(same_id(&gwp->gw_id, &sr->this.id));
-
ugh = "TXT RR for us has wrong key";
if (gwp->gw_key_present &&
private->belongs_to(private, gwp->key->public_key))
}
}
#ifdef USE_KEYRR
- if (ugh != NULL)
+ if (ugh)
{
/* if no TXT with right key, try KEY */
DBG(DBG_CONTROL,
/* We cannot seem to instantiate a suitable connection:
* complain clearly.
*/
- char ocb[ADDRTOT_BUF]
- , pcb[ADDRTOT_BUF]
- , pb[ADDRTOT_BUF];
+ char ocb[ADDRTOT_BUF], pcb[ADDRTOT_BUF];
addrtot(&b->our_client, 0, ocb, sizeof(ocb));
addrtot(&b->peer_client, 0, pcb, sizeof(pcb));
- passert(id_is_ipaddr(&ac->gateways_from_dns->gw_id));
- addrtot(&ac->gateways_from_dns->gw_id.ip_addr, 0, pb, sizeof(pb));
- loglog(RC_OPPOFAILURE
- , "no suitable connection for opportunism"
- " between %s and %s with %s as peer"
- , ocb, pcb, pb);
+ loglog(RC_OPPOFAILURE,
+ "no suitable connection for opportunism "
+ "between %s and %s with %Y as peer",
+ ocb, pcb, ac->gateways_from_dns->gw_id);
#ifdef KLIPS
if (b->held)
, ours, his, oppo_step_name[b->step], ugh ? ugh : "ok");
});
- if (ugh != NULL)
+ if (ugh)
{
b->policy_prio = c->prio;
b->failure_shunt = shunt_policy_spi(c, FALSE);
{
/* set up the next query */
struct find_oppo_continuation *cr = malloc_thing(struct find_oppo_continuation);
- struct id id;
+ identification_t *id;
b->policy_prio = c->prio;
b->failure_shunt = shunt_policy_spi(c, FALSE);
switch (next_step)
{
case fos_myid_ip_txt:
- if (c->spd.this.id.kind == ID_MYID
+ if (c->spd.this.id->get_type(c->spd.this.id) == ID_MYID
&& myid_state != MYID_SPECIFIED)
{
cr->b.failure_ok = TRUE;
cr->b.want = b->want = "TXT record for IP address as %myid";
- ugh = start_adns_query(&myids[MYID_IP]
- , &myids[MYID_IP]
- , T_TXT
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(myids[MYID_IP], myids[MYID_IP],
+ T_TXT, continue_oppo, &cr->ac);
break;
}
cr->b.step = fos_myid_hostname_txt;
/* fall through */
case fos_myid_hostname_txt:
- if (c->spd.this.id.kind == ID_MYID
+ if (c->spd.this.id->get_type(c->spd.this.id) == ID_MYID
&& myid_state != MYID_SPECIFIED)
{
#ifdef USE_KEYRR
cr->b.failure_ok = FALSE;
#endif
cr->b.want = b->want = "TXT record for hostname as %myid";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , &myids[MYID_HOSTNAME]
- , T_TXT
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(myids[MYID_HOSTNAME],
+ myids[MYID_HOSTNAME],
+ T_TXT, continue_oppo, &cr->ac);
break;
}
{
cr->b.failure_ok = TRUE;
cr->b.want = b->want = "KEY record for IP address as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_IP]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(myids[MYID_IP], NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
}
cr->b.step = fos_myid_hostname_key;
{
cr->b.failure_ok = FALSE; /* last attempt! */
cr->b.want = b->want = "KEY record for hostname as %myid (no good TXT)";
- ugh = start_adns_query(&myids[MYID_HOSTNAME]
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(myids[MYID_HOSTNAME], NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
}
#endif
* Note: {unshare|free}_id_content not needed for id: ephemeral.
*/
cr->b.want = b->want = "our client's TXT record";
- iptoid(&b->our_client, &id);
- ugh = start_adns_query(&id
- , &c->spd.this.id /* we are the security gateway */
- , T_TXT
- , continue_oppo
- , &cr->ac);
+ id = identification_create_from_sockaddr((sockaddr_t*)&b->our_client);
+ ugh = start_adns_query(id, c->spd.this.id, /* we are the security gateway */
+ T_TXT, continue_oppo, &cr->ac);
+ id->destroy(id);
break;
}
cr->b.step = fos_our_txt;
case fos_our_txt: /* TXT for us */
cr->b.failure_ok = b->failure_ok = TRUE;
cr->b.want = b->want = "our TXT record";
- ugh = start_adns_query(&sr->this.id
- , &sr->this.id /* we are the security gateway XXX - maybe ignore? mcr */
- , T_TXT
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(sr->this.id, sr->this.id, /* we are the security gateway */
+ T_TXT, continue_oppo, &cr->ac);
break;
#ifdef USE_KEYRR
case fos_our_key: /* KEY for us */
cr->b.want = b->want = "our KEY record";
cr->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&sr->this.id
- , (const struct id *) NULL /* security gateway meaningless */
- , T_KEY
- , continue_oppo
- , &cr->ac);
+ ugh = start_adns_query(sr->this.id, NULL, /* security gateway meaningless */
+ T_KEY, continue_oppo, &cr->ac);
break;
#endif /* USE_KEYRR */
/* note: {unshare|free}_id_content not needed for id: ephemeral */
cr->b.want = b->want = "target's TXT record";
cr->b.failure_ok = b->failure_ok = FALSE;
- iptoid(&b->peer_client, &id);
- ugh = start_adns_query(&id
- , (const struct id *) NULL /* security gateway unconstrained */
- , T_TXT
- , continue_oppo
- , &cr->ac);
+ id = identification_create_from_sockaddr((sockaddr_t*)&b->peer_client);
+ ugh = start_adns_query(id, NULL, /* security gateway unconstrained */
+ T_TXT, continue_oppo, &cr->ac);
+ id->destroy(id);
break;
default:
reset_cur_connection();
}
c = n;
- } while (c != NULL);
+ } while (c);
}
/* an ISAKMP SA has been established.
{
connection_t *next = d->ac_next; /* might move underneath us */
- if (d->kind >= CK_PERMANENT
- && same_id(&c->spd.this.id, &d->spd.this.id)
- && same_id(&c->spd.that.id, &d->spd.that.id)
- && !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
+ if (d->kind >= CK_PERMANENT &&
+ c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ c->spd.that.id->equals(c->spd.that.id, d->spd.that.id) &&
+ !sameaddr(&c->spd.that.host_addr, &d->spd.that.host_addr))
{
release_connection(d, FALSE);
}
, (fmt_conn_instance(best_ro, cib), cib)
, enum_name(&routing_story, best_ro->spd.routing));
- if (erop != NULL)
+ if (erop)
{
m = builddiag("%s; eroute owner:", m);
if (!erouted(best_ero->spd.routing))
DBG_log("%s", m);
});
- if (erop != NULL)
+ if (erop)
+ {
*erop = erouted(best_erouting)? best_ero : NULL;
-
- if (srp != NULL )
+ }
+ if (srp)
{
*srp = best_sr;
- if (esrp != NULL )
+ if (esrp)
+ {
*esrp = best_esr;
+ }
}
return routed(best_routing)? best_ro : NULL;
/* if we have requirements for the policy,
* choose the first matching connection.
*/
- while (c != NULL)
+ while (c)
{
if (c->policy & auth_requested)
{
#define PRIO_NO_MATCH_FOUND 2048
connection_t *refine_host_connection(const struct state *st,
- const struct id *peer_id,
+ identification_t *peer_id,
identification_t *peer_ca)
{
connection_t *c = st->st_connection;
const chunk_t *psk = NULL;
bool wcpip; /* wildcard Peer IP? */
int best_prio = PRIO_NO_MATCH_FOUND;
- int wildcards, our_pathlen, peer_pathlen;
+ int our_pathlen, peer_pathlen;
- if (same_id(&c->spd.that.id, peer_id)
- && trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen)
- && peer_pathlen == 0
- && match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen)
- && our_pathlen == 0)
+ if (c->spd.that.id->equals(c->spd.that.id, peer_id) &&
+ trusted_ca(peer_ca, c->spd.that.ca, &peer_pathlen) &&
+ peer_pathlen == 0 &&
+ match_requested_ca(c->requested_ca, c->spd.this.ca, &our_pathlen) &&
+ our_pathlen == 0)
{
DBG(DBG_CONTROL,
DBG_log("current connection is a full match"
{
const char *match_name[] = {"no", "ok"};
- bool matching_id = match_id(peer_id
- , &d->spd.that.id, &wildcards);
+ id_match_t match_level = peer_id->matches(peer_id, d->spd.that.id);
+
+ bool matching_id = match_level > ID_MATCH_NONE;
+
bool matching_auth = (d->policy & auth_policy) != LEMPTY;
bool matching_trust = trusted_ca(peer_ca
, d->spd.this.ca, &our_pathlen);
bool match = matching_id && matching_auth && matching_trust;
- int prio = (MAX_WILDCARDS + 1) * !matching_request + wildcards;
+ int prio = (ID_MATCH_PERFECT) * !matching_request +
+ ID_MATCH_PERFECT - match_level;
prio = (MAX_CA_PATH_LEN + 1) * prio + peer_pathlen;
prio = (MAX_CA_PATH_LEN + 1) * prio + our_pathlen;
* used (by another id) addr/net.
*/
static bool is_virtual_net_used(const ip_subnet *peer_net,
- const struct id *peer_id)
+ identification_t *peer_id)
{
connection_t *d;
case CK_INSTANCE:
if ((subnetinsubnet(peer_net,&d->spd.that.client) ||
subnetinsubnet(&d->spd.that.client,peer_net))
- && !same_id(&d->spd.that.id, peer_id))
+ && !d->spd.that.id->equals(d->spd.that.id, peer_id))
{
- char buf[BUF_LEN];
char client[SUBNETTOT_BUF];
subnettot(peer_net, 0, client, sizeof(client));
- idtoa(&d->spd.that.id, buf, sizeof(buf));
- plog("Virtual IP %s is already used by '%s'", client, buf);
- idtoa(peer_id, buf, sizeof(buf));
- plog("Your ID is '%s'", buf);
+ plog("Virtual IP %s is already used by '%Y'",
+ client, d->spd.that.id);
+ plog("Your ID is '%Y'", peer_id);
+
return TRUE; /* already used by another one */
}
break;
#define PATH_WEIGHT 1
#define WILD_WEIGHT (MAX_CA_PATH_LEN+1)
-#define PRIO_WEIGHT (MAX_WILDCARDS+1)*WILD_WEIGHT
+#define PRIO_WEIGHT (ID_MATCH_PERFECT+1) * WILD_WEIGHT
/* fc_try: a helper function for find_client_connection */
static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
- const struct id *peer_id,
+ identification_t *peer_id,
const ip_subnet *our_net,
const ip_subnet *peer_net,
const u_int8_t our_protocol,
connection_t *d;
connection_t *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ id_match_t match_level;
+ int pathlen;
+
const bool peer_net_is_host = subnetisaddr(peer_net, &c->spd.that.host_addr);
continue;
}
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
+ match_level = c->spd.that.id->matches(c->spd.that.id, d->spd.that.id);
+
+ if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ (match_level > ID_MATCH_NONE) &&
+ trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
+ match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
{
continue;
}
}
if (is_virtual_connection(d)
&& (!is_virtual_net_allowed(d, peer_net, &c->spd.that.host_addr)
- || is_virtual_net_used(peer_net, peer_id?peer_id:&c->spd.that.id)))
+ || is_virtual_net_used(peer_net, peer_id?peer_id:c->spd.that.id)))
{
continue;
}
* - given that, the shortest CA pathlength is preferred
*/
prio = PRIO_WEIGHT * routed(sr->routing)
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + WILD_WEIGHT * match_level
+ PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen)
+ 1;
if (prio > best_prio)
}
}
- if (best != NULL && NEVER_NEGOTIATE(best->policy))
+ if (best && NEVER_NEGOTIATE(best->policy))
+ {
best = NULL;
-
+ }
DBG(DBG_CONTROLMORE,
DBG_log(" fc_try concluding with %s [%ld]"
, (best ? best->name : "none"), best_prio)
connection_t *d;
connection_t *best = NULL;
policy_prio_t best_prio = BOTTOM_PRIO;
- int wildcards, pathlen;
+ id_match_t match_level;
+ int pathlen;
for (d = hp->connections; d != NULL; d = d->hp_next)
{
{
continue;
}
- if (!(same_id(&c->spd.this.id, &d->spd.this.id)
- && match_id(&c->spd.that.id, &d->spd.that.id, &wildcards)
- && trusted_ca(peer_ca, d->spd.that.ca, &pathlen)
- && match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
+ match_level = c->spd.that.id->matches(c->spd.that.id, c->spd.that.id);
+
+ if (!(c->spd.this.id->equals(c->spd.this.id, d->spd.this.id) &&
+ (match_level > ID_MATCH_NONE) &&
+ trusted_ca(peer_ca, d->spd.that.ca, &pathlen) &&
+ match_group_membership(peer_attributes, d->name, d->spd.that.groups)))
{
continue;
}
* - given that, the shortest CA pathlength is preferred
*/
prio = PRIO_WEIGHT * (d->prio + routed(sr->routing))
- + WILD_WEIGHT * (MAX_WILDCARDS - wildcards)
+ + WILD_WEIGHT * match_level
+ PATH_WEIGHT * (MAX_CA_PATH_LEN - pathlen);
if (prio > best_prio)
{
}
/* if the best wasn't opportunistic, we fail: it must be a shunt */
- if (best != NULL
- && (NEVER_NEGOTIATE(best->policy)
- || (best->policy & POLICY_OPPO) == LEMPTY))
+ if (best && (NEVER_NEGOTIATE(best->policy) ||
+ (best->policy & POLICY_OPPO) == LEMPTY))
{
best = NULL;
}
#endif /* DEBUG */
}
- if (hp != NULL)
+ if (hp)
{
/* RW match with actual peer_id or abstract peer_id? */
d = fc_try(c, hp, NULL, our_net, peer_net
/* DBG_log("comparing %s to %s", ca->name, cb->name); */
ret = strcasecmp(ca->name, cb->name);
- if (ret != 0)
+ if (ret)
+ {
return ret;
+ }
ret = ca->kind - cb->kind; /* note: enum connection_kind behaves like int */
- if (ret != 0)
+ if (ret)
+ {
return ret;
+ }
/* same name, and same type */
switch (ca->kind)
/* show topology */
{
- char topo[CONNECTION_BUF];
+ char topo[BUF_LEN];
struct spd_route *sr = &c->spd;
int num=0;
- while (sr != NULL)
+ while (sr)
{
(void) format_connection(topo, sizeof(topo), c, sr);
whack_log(RC_COMMENT, "\"%s\"%s: %s; %s; eroute owner: #%lu"
}
/* show group attributes if defined */
- if (c->spd.that.groups != NULL)
+ if (c->spd.that.groups)
{
whack_log(RC_COMMENT, "\"%s\"%s: groups: %s"
, c->name
bool already_queued = FALSE;
struct pending *p = c->host_pair->pending;
- while (p != NULL)
+ while (p)
{
if (streq(c->name, p->connection->name))
{
struct pending *p = *pp;
*pp = p->next;
- if (p->connection != NULL)
+ if (p->connection)
+ {
connection_discard(p->connection);
+ }
close_any(p->whack_sock);
free(p);
}
{
struct host_pair *hp = st->st_connection->host_pair;
- if (hp != NULL)
+ if (hp)
{
struct pending **pp
, *p;
/* a connection has been deleted; discard any related pending */
static void flush_pending_by_connection(connection_t *c)
{
- if (c->host_pair != NULL)
+ if (c->host_pair)
{
struct pending **pp
, *p;
ue = NULL;
- while (sr1 != NULL && ue != NULL)
+ while (sr1 && ue)
{
for (ue = connections; ue != NULL; ue = ue->ac_next)
{
struct spd_route *srue = &ue->spd;
- while (srue != NULL
- && srue->routing == RT_ROUTED_ECLIPSED
+ while (srue && srue->routing == RT_ROUTED_ECLIPSED
&& !(samesubnet(&sr1->this.client, &srue->this.client)
&& samesubnet(&sr1->that.client, &srue->that.client)))
{
srue = srue->next;
}
- if (srue != NULL && srue->routing==RT_ROUTED_ECLIPSED)
+ if (srue && srue->routing == RT_ROUTED_ECLIPSED)
{
*esrp = srue;
break;
/* information about connections between hosts and clients
* Copyright (C) 1998-2001 D. Hugh Redelmeier
+ * Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
#include <utils/linked_list.h>
#include <utils/identification.h>
+#include <credentials/ietf_attributes/ietf_attributes.h>
-#include "id.h"
#include "certs.h"
-#include "ac.h"
#include "smartcard.h"
#include "whack.h"
struct virtual_t;
struct end {
- struct id id;
+ identification_t *id;
ip_address
host_addr,
host_nexthop,
extern bool orient(connection_t *c);
extern bool same_peer_ids(const connection_t *c, const connection_t *d,
- const struct id *his_id);
+ identification_t *his_id);
/* Format the topology of a connection end, leaving out defaults.
* Largest left end looks like: client === host : port [ host_id ] --- hop
extern bool uniqueIDs; /* --uniqueids? */
extern void ISAKMP_SA_established(connection_t *c, so_serial_t serial);
-#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \
- && (id_is_ipaddr(&(c)->spd.that.id)? \
- sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE))
+#define id_is_ipaddr(id) ((id)->get_type(id) == ID_IPV4_ADDR || \
+ (id)->get_type(id) == ID_IPV6_ADDR)
+extern bool his_id_was_instantiated(const connection_t *c);
struct state; /* forward declaration of tag (defined in state.h) */
const ip_address *him,
u_int16_t his_port, lset_t policy);
extern connection_t* refine_host_connection(const struct state *st,
- const struct id *id,
+ identification_t *id,
identification_t *peer_ca);
extern connection_t* find_client_connection(connection_t *c,
const ip_subnet *our_net,
*/
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
-extern connection_t *rw_instantiate(connection_t *c
- , const ip_address *him
- , u_int16_t his_port
- , const ip_subnet *his_net
- , const struct id *his_id);
-
-extern connection_t *oppo_instantiate(connection_t *c
- , const ip_address *him
- , const struct id *his_id
- , struct gw_info *gw
- , const ip_address *our_client
- , const ip_address *peer_client);
+extern connection_t *rw_instantiate(connection_t *c,
+ const ip_address *him,
+ u_int16_t his_port,
+ const ip_subnet *his_net,
+ identification_t *his_id);
+
+extern connection_t *oppo_instantiate(connection_t *c,
+ const ip_address *him,
+ identification_t *his_id,
+ struct gw_info *gw,
+ const ip_address *our_client,
+ const ip_address *peer_client);
extern connection_t
- *build_outgoing_opportunistic_connection(struct gw_info *gw
- , const ip_address *our_client
- , const ip_address *peer_client);
+ *build_outgoing_opportunistic_connection(struct gw_info *gw,
+ const ip_address *our_client,
+ const ip_address *peer_client);
-/* worst case: "[" serial "] " myclient "=== ..." peer "===" hisclient '\0' */
-#define CONN_INST_BUF \
- (2 + 10 + 1 + SUBNETTOT_BUF + 7 + ADDRTOT_BUF + 3 + SUBNETTOT_BUF + 1)
+#define CONN_INST_BUF BUF_LEN
-extern void fmt_conn_instance(const connection_t *c
- , char buf[CONN_INST_BUF]);
+extern void fmt_conn_instance(const connection_t *c, char buf[CONN_INST_BUF]);
/* operations on "pending", the structure representing Quick Mode
* negotiations delayed until a Keying Channel has been negotiated.
struct pending; /* forward declaration (opaque outside connections.c) */
-extern void add_pending(int whack_sock
- , struct state *isakmp_sa
- , connection_t *c
- , lset_t policy
- , unsigned long try
- , so_serial_t replacing);
+extern void add_pending(int whack_sock, struct state *isakmp_sa,
+ connection_t *c, lset_t policy, unsigned long try,
+ so_serial_t replacing);
extern void release_pending_whacks(struct state *st, err_t story);
extern void unpend(struct state *st);
#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
#include "log.h"
-#include "id.h"
+#include "myid.h"
#include "connections.h"
#include "keys.h" /* needs connections.h */
#include "dnskey.h"
#define our_TXT_attr_string "X-IPsec-Server"
static const char our_TXT_attr[] = our_TXT_attr_string;
-static err_t
-decode_iii(u_char **pp, struct id *gw_id)
+identification_t* decode_iii(u_char **pp)
{
+ identification_t *gw_id;
u_char *p = *pp + strspn(*pp, " \t");
u_char *e = p + strcspn(p, " \t");
u_char under = *e;
if (p == e)
{
- return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+ return NULL;
}
*e = '\0';
- if (*p == '@')
- {
- /* gateway specification in this record is @FQDN */
- err_t ugh = atoid(p, gw_id, FALSE);
-
- if (ugh != NULL)
- {
- return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
- , ugh);
- }
- }
- else
- {
- /* gateway specification is numeric */
- ip_address ip;
- err_t ugh = tnatoaddr(p, e-p
- , strchr(p, ':') == NULL? AF_INET : AF_INET6
- , &ip);
-
- if (ugh != NULL)
- {
- return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
- , ugh);
- }
- if (isanyaddr(&ip))
- {
- return "gateway address must not be 0.0.0.0 or 0::0";
- }
- iptoid(&ip, gw_id);
- }
-
+ gw_id = identification_create_from_string(p);
*e = under;
*pp = e + strspn(e, " \t");
- return NULL;
+ return gw_id;
}
-static err_t
-process_txt_rr_body(u_char *str
-, bool doit /* should we capture information? */
-, enum dns_auth_level dns_auth_level
-, struct adns_continuation *const cr)
+static err_t process_txt_rr_body(u_char *str, bool doit,
+ enum dns_auth_level dns_auth_level,
+ struct adns_continuation *const cr)
{
- const struct id *client_id = &cr->id; /* subject of query */
+ identification_t *client_id = cr->id; /* subject of query */
u_char *p = str;
unsigned long pref = 0;
struct gw_info gi;
p += strspn(p, " \t");
/* Decode iii (Security Gateway ID). */
-
zero(&gi); /* before first use */
- TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
+ gi.gw_id = decode_iii(&p);
+ if (gi.gw_id == NULL)
+ {
+ return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
+ }
if (!cr->sgw_specified)
{
* and we don't know who to initiate with.
* So we're looking for gateway specs with an IP address
*/
- if (!id_is_ipaddr(&gi.gw_id))
+ if (gi.gw_id->get_type(gi.gw_id) != ID_IPV4_ADDR &&
+ gi.gw_id->get_type(gi.gw_id) != ID_IPV6_ADDR)
{
DBG(DBG_DNS,
- {
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored because gateway's IP is unspecified"
- , our_TXT_attr, cidb, gwidb);
- });
+ DBG_log("TXT %s record for '%Y': security gateway '%Y';"
+ " ignored because gateway's IP is unspecified",
+ our_TXT_attr, client_id, gi.gw_id);
+ )
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
/* We do know the peer's ID (because we are responding)
* So we're looking for gateway specs specifying this known ID.
*/
- const struct id *peer_id = &cr->sgw_id;
+ identification_t *peer_id = cr->sgw_id;
- if (!same_id(peer_id, &gi.gw_id))
+ if (!peer_id->equals(peer_id, gi.gw_id))
{
DBG(DBG_DNS,
- {
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
- char pidb[BUF_LEN];
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- idtoa(peer_id, pidb, sizeof(pidb));
- DBG_log("TXT %s record for %s: security gateway %s;"
- " ignored -- looking to confirm %s as gateway"
- , our_TXT_attr, cidb, gwidb, pidb);
- });
+ DBG_log("TXT %s record for '%Y': security gateway '%Y';"
+ " ignored -- looking to confirm '%Y' as gateway",
+ our_TXT_attr, client_id, gi.gw_id, peer_id);
+ )
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
/* really accept gateway */
struct gw_info **gwip; /* gateway insertion point */
- gi.client_id = *client_id; /* will need to unshare_id_content */
+ gi.client_id = client_id; /* will need to unshare_id_content */
/* decode optional kkk: base 64 encoding of key */
DBG(DBG_DNS,
{
- char cidb[BUF_LEN];
- char gwidb[BUF_LEN];
chunk_t keyid;
- public_key_t *key;
-
- idtoa(client_id, cidb, sizeof(cidb));
- idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
- key = gi.key->public_key;
+ public_key_t *key = gi.key->public_key;
if (gi.gw_key_present &&
key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid))
{
- DBG_log("gateway for %s is %s with key %#B"
- , cidb, gwidb, &keyid);
+ DBG_log("gateway for %s is %s with key %#B",
+ client_id, gi.gw_id, &keyid);
}
else
{
- DBG_log("gateway for %s is %s; no key specified"
- , cidb, gwidb);
+ DBG_log("gateway for '%Y' is '%Y'; no key specified",
+ client_id, gi.gw_id);
}
});
gi.next = *gwip;
*gwip = clone_thing(gi);
- unshare_id_content(&(*gwip)->gw_id);
- unshare_id_content(&(*gwip)->client_id);
+ (*gwip)->gw_id = (*gwip)->gw_id->clone((*gwip)->gw_id);
+ (*gwip)->client_id = (*gwip)->client_id->clone((*gwip)->client_id);
}
return NULL;
/****************************************************************/
-static err_t
-build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
-, unsigned long serial USED_BY_DEBUG
-, const struct id *id
-, const char *typename USED_BY_DEBUG
-, const char *gwname USED_BY_DEBUG)
+static err_t build_dns_name(u_char name_buf[NS_MAXDNAME + 2],
+ unsigned long serial USED_BY_DEBUG,
+ identification_t *id,
+ const char *typename USED_BY_DEBUG,
+ identification_t *gw USED_BY_DEBUG)
{
/* note: all end in "." to suppress relative searches */
id = resolve_myid(id);
- switch (id->kind)
- {
- case ID_IPV4_ADDR:
- {
- /* XXX: this is really ugly and only temporary until addrtot can
- * generate the correct format
- */
- const unsigned char *b;
- size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
- passert(bl == 4);
- snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
- , b[3], b[2], b[1], b[0]);
- break;
- }
-
- case ID_IPV6_ADDR:
+ switch (id->get_type(id))
{
- /* ??? is this correct? */
- const unsigned char *b;
- size_t bl;
- u_char *op = name_buf;
- static const char suffix[] = "IP6.INT.";
-
- for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
+ case ID_IPV4_ADDR:
{
- if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
- return "IPv6 reverse name too long";
- op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
- }
- strcpy(op, suffix);
- break;
- }
+ chunk_t b = id->get_encoding(id);
- case ID_FQDN:
- /* strip trailing "." characters, then add one */
+ snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa.",
+ b.ptr[3], b.ptr[2], b.ptr[1], b.ptr[0]);
+ break;
+ }
+ case ID_IPV6_ADDR:
{
- size_t il = id->name.len;
+ chunk_t b = id->get_encoding(id);
+ size_t bl;
+ u_char *op = name_buf;
+ static const char suffix[] = "IP6.INT.";
- while (il > 0 && id->name.ptr[il - 1] == '.')
- il--;
- if (il > NS_MAXDNAME)
+ for (bl = b.len; bl-- != 0; )
+ {
+ if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
+ {
+ return "IPv6 reverse name too long";
+ }
+ op += sprintf(op, "%x.%x.", b.ptr[bl] & 0xF, b.ptr[bl] >> 4);
+ }
+ strcpy(op, suffix);
+ break;
+ }
+ case ID_FQDN:
+ {
+ if (snprintf(name_buf, NS_MAXDNAME + 2, "%Y.", id) > NS_MAXDNAME + 1)
+ {
return "FQDN too long for domain name";
-
- memcpy(name_buf, id->name.ptr, il);
- strcpy(name_buf + il, ".");
+ }
+ break;
}
- break;
-
- default:
- return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
+ default:
+ return "can only query DNS for key for ID that is a FQDN, IPV4_ADDR, or IPV6_ADDR";
}
- DBG(DBG_CONTROL | DBG_DNS, DBG_log("DNS query %lu for %s for %s (gw: %s)"
- , serial, typename, name_buf, gwname));
+ DBG(DBG_CONTROL | DBG_DNS,
+ DBG_log("DNS query %lu for %s for %s (gw: %Y)", serial, typename, name_buf, gw)
+ )
return NULL;
}
-void
-gw_addref(struct gw_info *gw)
+void gw_addref(struct gw_info *gw)
{
if (gw != NULL)
{
}
}
-void
-gw_delref(struct gw_info **gwp)
+void gw_delref(struct gw_info **gwp)
{
struct gw_info *gw = *gwp;
gw->refcnt--;
if (gw->refcnt == 0)
{
- free_id_content(&gw->client_id);
- free_id_content(&gw->gw_id);
+ DESTROY_IF(gw->client_id);
+ DESTROY_IF(gw->gw_id);
if (gw->gw_key_present)
+ {
unreference_key(&gw->key);
+ }
gw_delref(&gw->next);
free(gw); /* trickery could make this a tail-call */
}
static struct adns_continuation *continuations = NULL; /* newest of queue */
static struct adns_continuation *next_query = NULL; /* oldest not sent */
-static struct adns_continuation *
-continuation_for_qtid(unsigned long qtid)
+static struct adns_continuation *continuation_for_qtid(unsigned long qtid)
{
struct adns_continuation *cr = NULL;
if (qtid != 0)
+ {
for (cr = continuations; cr != NULL && cr->qtid != qtid; cr = cr->previous)
;
+ }
return cr;
}
-static void
-release_adns_continuation(struct adns_continuation *cr)
+static void release_adns_continuation(struct adns_continuation *cr)
{
passert(cr != next_query);
gw_delref(&cr->gateways_from_dns);
#ifdef USE_KEYRR
free_public_keys(&cr->keys_from_dns);
#endif /* USE_KEYRR */
- unshare_id_content(&cr->id);
- unshare_id_content(&cr->sgw_id);
+ cr->id = cr->id->clone(cr->id);
+ cr->sgw_id = cr->sgw_id->clone(cr->sgw_id);
/* unlink from doubly-linked list */
if (cr->next == NULL)
{
- passert(continuations == cr);
continuations = cr->previous;
}
else
{
- passert(cr->next->previous == cr);
cr->next->previous = cr->previous;
}
if (cr->previous != NULL)
{
- passert(cr->previous->next == cr);
cr->previous->next = cr->next;
}
free(cr);
}
-err_t
-start_adns_query(const struct id *id /* domain to query */
-, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
-, int type /* T_TXT or T_KEY, selecting rr type of interest */
-, cont_fn_t cont_fn
-, struct adns_continuation *cr)
+err_t start_adns_query(identification_t *id, /* domain to query */
+ identification_t *sgw_id, /* if non-null, any accepted gw_info must match */
+ int type, /* T_TXT or T_KEY, selecting rr type of interest */
+ cont_fn_t cont_fn,
+ struct adns_continuation *cr)
{
static unsigned long qtid = 1; /* query transaction id; NOTE: static */
const char *typename = rr_typename(type);
- char gwidb[BUF_LEN];
- if(adns_pid == 0
- && adns_restart_count < ADNS_RESTART_MAX)
+ if(adns_pid == 0 && adns_restart_count < ADNS_RESTART_MAX)
{
plog("ADNS helper was not running. Restarting attempt %d",adns_restart_count);
init_adns();
}
-
/* Splice this in at head of doubly-linked list of continuations.
* Note: this must be done before any release_adns_continuation().
*/
cr->previous = continuations;
if (continuations != NULL)
{
- passert(continuations->next == NULL);
continuations->next = cr;
}
continuations = cr;
cr->qtid = qtid++;
cr->type = type;
cr->cont_fn = cont_fn;
- cr->id = *id;
- unshare_id_content(&cr->id);
- cr->sgw_specified = sgw_id != NULL;
- cr->sgw_id = cr->sgw_specified? *sgw_id : empty_id;
- unshare_id_content(&cr->sgw_id);
+ cr->id = id->clone(id);
+ cr->sgw_specified = (sgw_id != NULL);
+ cr->sgw_id = cr->sgw_specified ?
+ sgw_id->clone(sgw_id) :
+ identification_create_from_string("%any");
cr->gateways_from_dns = NULL;
#ifdef USE_KEYRR
cr->keys_from_dns = NULL;
cr->debugging = LEMPTY;
#endif
- idtoa(&cr->sgw_id, gwidb, sizeof(gwidb));
-
zero(&cr->query);
-
{
- err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid
- , id, typename, gwidb);
+ err_t ugh = build_dns_name(cr->query.name_buf, cr->qtid, id,
+ typename, cr->sgw_id);
- if (ugh != NULL)
+ if (ugh)
{
release_adns_continuation(cr);
return ugh;
* Returns with error message iff lwdnsq result is malformed.
* Most errors will be in DNS data and will be handled by cr->cont_fn.
*/
-static err_t
-process_lwdnsq_answer(char *ts)
+static err_t process_lwdnsq_answer(char *ts)
{
err_t ugh = NULL;
char *rest;
}
#endif /* USE_LWRES */
-static void
-recover_adns_die(void)
+static void recover_adns_die(void)
{
struct adns_continuation *cr = NULL;
adns_restart_count=0;
}
-void
-handle_adns_answer(void)
+void handle_adns_answer(void)
{
/* These are retained across calls to handle_adns_answer. */
static size_t buflen = 0; /* bytes in answer buffer */
* for more details.
*/
-extern int
- adns_qfd, /* file descriptor for sending queries to adns */
- adns_afd; /* file descriptor for receiving answers from adns */
+#include <utils/identification.h>
+
+extern int adns_qfd; /* file descriptor for sending queries to adns */
+extern int adns_afd; /* file descriptor for receiving answers from adns */
extern const char *pluto_adns_option; /* path from --pluto_adns */
extern void init_adns(void);
extern void stop_adns(void);
typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh);
struct adns_continuation {
- unsigned long qtid; /* query transaction id number */
- int type; /* T_TXT or T_KEY, selecting rr type of interest */
- cont_fn_t cont_fn; /* function to carry on suspended work */
- struct id id; /* subject of query */
+ unsigned long qtid; /* query transaction id number */
+ int type; /* T_TXT or T_KEY, selecting rr type of interest */
+ cont_fn_t cont_fn; /* function to carry on suspended work */
+ identification_t *id; /* subject of query */
bool sgw_specified;
- struct id sgw_id; /* peer, if constrained */
- lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
+ identification_t *sgw_id; /* peer, if constrained */
+ lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
#ifdef USE_KEYRR
struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
struct adns_continuation *previous, *next;
struct pubkey *last_info; /* the last structure we accumulated */
#ifdef USE_LWRES
- bool used; /* have we called the cont_fn yet? */
+ bool used; /* have we called the cont_fn yet? */
struct {
u_char name_buf[NS_MAXDNAME + 2];
} query;
#endif /* ! USE_LWRES */
};
-extern err_t start_adns_query(const struct id *id /* domain to query */
- , const struct id *sgw_id /* if non-null, any accepted gw_info must match */
+extern err_t start_adns_query(identification_t *id /* domain to query */
+ , identification_t *sgw_id /* if non-null, any accepted gw_info must match */
, int type /* T_TXT or T_KEY, selecting rr type of interest */
, cont_fn_t cont_fn /* continuation function */
, struct adns_continuation *cr);
/* Gateway info gleaned from reverse DNS of client */
struct gw_info {
- unsigned refcnt; /* reference counted! */
- unsigned pref; /* preference: lower is better */
-#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
- struct id client_id; /* id of client of peer */
- struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
+ unsigned refcnt; /* reference counted! */
+ unsigned pref; /* preference: lower is better */
+#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
+ identification_t* client_id; /* id of client of peer */
+ identification_t* gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
bool gw_key_present;
struct pubkey *key;
struct gw_info *next;
};
-extern void gw_addref(struct gw_info *gw)
- , gw_delref(struct gw_info **gwp);
-
+extern void gw_addref(struct gw_info *gw);
+extern void gw_delref(struct gw_info **gwp);
extern void reset_adns_restart_count(void);
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "x509.h"
#include "ca.h"
#include "whack.h"
+++ /dev/null
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-2001 D. Hugh Redelmeier
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
-#include <errno.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-#include <unistd.h>
-#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
-# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
-#endif
-#include <sys/queue.h>
-
-#include <freeswan.h>
-
-#include "constants.h"
-#include "defs.h"
-#include "id.h"
-#include "log.h"
-#include "connections.h"
-#include "packet.h"
-#include "whack.h"
-
-const struct id empty_id; /* ID_ANY */
-
-enum myid_state myid_state = MYID_UNKNOWN;
-struct id myids[MYID_SPECIFIED+1]; /* %myid */
-char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
-
-/* initialize id module
- * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
- */
-void init_id(void)
-{
- passert(empty_id.kind == ID_ANY);
- myid_state = MYID_UNKNOWN;
- {
- enum myid_state s;
-
- for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
- {
- myids[s] = empty_id;
- myid_str[s] = NULL;
- }
- }
- set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
- set_myid(MYID_IP, getenv("defaultrouteaddr"));
- set_myFQDN();
-}
-
-/*
- * free id module
- */
-void free_id(void)
-{
- enum myid_state s;
-
- for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
- {
- free_id_content(&myids[s]);
- free(myid_str[s]);
- }
-}
-
-static void calc_myid_str(enum myid_state s)
-{
- /* preformat the ID name */
- char buf[BUF_LEN];
-
- idtoa(&myids[s], buf, BUF_LEN);
- replace(myid_str[s], clone_str(buf));
-}
-
-
-void set_myid(enum myid_state s, char *idstr)
-{
- if (idstr != NULL)
- {
- struct id id;
- err_t ugh = atoid(idstr, &id, FALSE);
-
- if (ugh != NULL)
- {
- loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr);
- }
- else
- {
- free_id_content(&myids[s]);
- unshare_id_content(&id);
- myids[s] = id;
- if (s == MYID_SPECIFIED)
- myid_state = MYID_SPECIFIED;
-
- calc_myid_str(s);
- }
- }
-}
-
-void set_myFQDN(void)
-{
- char FQDN[HOST_NAME_MAX + 1];
- int r = gethostname(FQDN, sizeof(FQDN));
-
- free_id_content(&myids[MYID_HOSTNAME]);
- myids[MYID_HOSTNAME] = empty_id;
- if (r != 0)
- {
- log_errno((e, "gethostname() failed in set_myFQDN"));
- }
- else
- {
- FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
-
- {
- size_t len = strlen(FQDN);
-
- if (len > 0 && FQDN[len-1] == '.')
- {
- /* nuke trailing . */
- FQDN[len-1]='\0';
- }
- }
-
- if (!strcaseeq(FQDN, "localhost.localdomain"))
- {
- chunk_t myid_name = { FQDN, strlen(FQDN) };
-
- myids[MYID_HOSTNAME].name = chunk_clone(myid_name);
- myids[MYID_HOSTNAME].kind = ID_FQDN;
- calc_myid_str(MYID_HOSTNAME);
- }
- }
-}
-
-void show_myid_status(void)
-{
- char idstr[BUF_LEN];
-
- (void)idtoa(&myids[myid_state], idstr, sizeof(idstr));
- whack_log(RC_COMMENT, "%%myid = %s", idstr);
-}
-
-/* Convert textual form of id into a (temporary) struct id.
- * Note that if the id is to be kept, unshare_id_content will be necessary.
- */
-err_t atoid(char *src, struct id *id, bool myid_ok)
-{
- err_t ugh = NULL;
-
- *id = empty_id;
-
- if (myid_ok && streq("%myid", src))
- {
- id->kind = ID_MYID;
- }
- else if (strchr(src, '=') != NULL)
- {
- /* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */
- id->kind = ID_DER_ASN1_DN;
- id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */
- id->name.len = 0;
- /* convert from LDAP style or openssl x509 -subject style to ASN.1 DN
- * discard optional @ character in front of DN
- */
- ugh = atodn((*src == '@')?src+1:src, &id->name);
- }
- else if (strchr(src, '@') == NULL)
- {
- if (streq(src, "%any") || streq(src, "0.0.0.0"))
- {
- /* any ID will be accepted */
- id->kind = ID_ANY;
- }
- else
- {
- /* !!! this test is not sufficient for distinguishing address families.
- * We need a notation to specify that a FQDN is to be resolved to IPv6.
- */
- const struct af_info *afi = strchr(src, ':') == NULL
- ? &af_inet4_info: &af_inet6_info;
-
- id->kind = afi->id_addr;
- ugh = ttoaddr(src, 0, afi->af, &id->ip_addr);
- }
- }
- else
- {
- if (*src == '@')
- {
- if (*(src+1) == '#')
- {
- /* if there is a second specifier (#) on the line
- * we interprete this as ID_KEY_ID
- */
- id->kind = ID_KEY_ID;
- id->name.ptr = src;
- /* discard @~, convert from hex to bin */
- ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
- }
- else if (*(src+1) == '~')
- {
- /* if there is a second specifier (~) on the line
- * we interprete this as a binary ID_DER_ASN1_DN
- */
- id->kind = ID_DER_ASN1_DN;
- id->name.ptr = src;
- /* discard @~, convert from hex to bin */
- ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
- }
- else
- {
- id->kind = ID_FQDN;
- id->name.ptr = src+1; /* discard @ */
- id->name.len = strlen(src)-1;
- }
- }
- else
- {
- /* We leave in @, as per DOI 4.6.2.4
- * (but DNS wants . instead).
- */
- id->kind = ID_USER_FQDN;
- id->name.ptr = src;
- id->name.len = strlen(src);
- }
- }
- return ugh;
-}
-
-
-/*
- * Converts a binary key ID into hexadecimal format
- */
-int keyidtoa(char *dst, size_t dstlen, chunk_t keyid)
-{
- int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen);
- return (((size_t)n < dstlen)? n : dstlen) - 1;
-}
-
-void iptoid(const ip_address *ip, struct id *id)
-{
- *id = empty_id;
-
- switch (addrtypeof(ip))
- {
- case AF_INET:
- id->kind = ID_IPV4_ADDR;
- break;
- case AF_INET6:
- id->kind = ID_IPV6_ADDR;
- break;
- default:
- bad_case(addrtypeof(ip));
- }
- id->ip_addr = *ip;
-}
-
-int idtoa(const struct id *id, char *dst, size_t dstlen)
-{
- int n;
-
- id = resolve_myid(id);
- switch (id->kind)
- {
- case ID_ANY:
- n = snprintf(dst, dstlen, "(none)");
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
- break;
- case ID_FQDN:
- n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
- break;
- case ID_USER_FQDN:
- n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
- break;
- case ID_DER_ASN1_DN:
- n = dntoa(dst, dstlen, id->name);
- break;
- case ID_KEY_ID:
- n = keyidtoa(dst, dstlen, id->name);
- break;
- default:
- n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
- break;
- }
-
- /* "Sanitize" string so that log isn't endangered:
- * replace unprintable characters with '?'.
- */
- if (n > 0)
- {
- for ( ; *dst != '\0'; dst++)
- if (!isprint(*dst))
- *dst = '?';
- }
-
- return n;
-}
-
-/* Replace the shell metacharacters ', \, ", `, and $ in a character string
- * by escape sequences consisting of their octal values
- */
-void escape_metachar(const char *src, char *dst, size_t dstlen)
-{
- while (*src != '\0' && dstlen > 4)
- {
- switch (*src)
- {
- case '\'':
- case '\\':
- case '"':
- case '`':
- case '$':
- sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
- dst += 4;
- dstlen -= 4;
- break;
- default:
- *dst++ = *src;
- dstlen--;
- }
- src++;
- }
- *dst = '\0';
-}
-
-
-/* Make private copy of string in struct id.
- * This is needed if the result of atoid is to be kept.
- */
-void unshare_id_content(struct id *id)
-{
- switch (id->kind)
- {
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- id->name = chunk_clone(id->name);
- break;
- case ID_MYID:
- case ID_ANY:
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- break;
- default:
- bad_case(id->kind);
- }
-}
-
-void free_id_content(struct id *id)
-{
- switch (id->kind)
- {
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- free(id->name.ptr);
- break;
- case ID_MYID:
- case ID_ANY:
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- break;
- default:
- bad_case(id->kind);
- }
-}
-
-/* compare two struct id values */
-bool same_id(const struct id *a, const struct id *b)
-{
- a = resolve_myid(a);
- b = resolve_myid(b);
- if (a->kind != b->kind)
- return FALSE;
- switch (a->kind)
- {
- case ID_ANY:
- return TRUE; /* kind of vacuous */
-
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- return sameaddr(&a->ip_addr, &b->ip_addr);
-
- case ID_FQDN:
- case ID_USER_FQDN:
- /* assumptions:
- * - case should be ignored
- * - trailing "." should be ignored (even if the only character?)
- */
- {
- size_t al = a->name.len
- , bl = b->name.len;
-
- while (al > 0 && a->name.ptr[al - 1] == '.')
- al--;
- while (bl > 0 && b->name.ptr[bl - 1] == '.')
- bl--;
- return al == bl
- && strncasecmp(a->name.ptr, b->name.ptr, al) == 0;
- }
-
- case ID_DER_ASN1_DN:
- return same_dn(a->name, b->name);
-
- case ID_KEY_ID:
- return a->name.len == b->name.len
- && memeq(a->name.ptr, b->name.ptr, a->name.len);
-
- default:
- bad_case(a->kind);
- }
- return FALSE;
-}
-
-/* compare two struct id values, DNs can contain wildcards */
-bool match_id(const struct id *a, const struct id *b, int *wildcards)
-{
- if (b->kind == ID_ANY)
- {
- *wildcards = MAX_WILDCARDS;
- return TRUE;
- }
- if (a->kind != b->kind)
- return FALSE;
- if (a->kind == ID_DER_ASN1_DN)
- return match_dn(a->name, b->name, wildcards);
- else
- {
- *wildcards = 0;
- return same_id(a, b);
- }
-}
-
-/* count the numer of wildcards in an id */
-int id_count_wildcards(const struct id *id)
-{
- switch (id->kind)
- {
- case ID_ANY:
- return MAX_WILDCARDS;
- case ID_DER_ASN1_DN:
- return dn_count_wildcards(id->name);
- default:
- return 0;
- }
-}
-
-/* build an ID payload
- * Note: no memory is allocated for the body of the payload (tl->ptr).
- * We assume it will end up being a pointer into a sufficiently
- * stable datastructure. It only needs to last a short time.
- */
-void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
-{
- const struct id *id = resolve_myid(&end->id);
-
- zero(hd);
- hd->isaiid_idtype = id->kind;
- switch (id->kind)
- {
- case ID_ANY:
- hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
- tl->len = addrbytesptr(&end->host_addr
- , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
- break;
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- *tl = id->name;
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- tl->len = addrbytesptr(&id->ip_addr
- , (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
- break;
- default:
- bad_case(id->kind);
- }
-}
-
-/**
- * Converts libstrongswan's identification_t type into pluto's struct id
- */
-void id_from_identification(struct id *id, identification_t *identification)
-{
- chunk_t encoding;
-
- encoding = identification->get_encoding(identification);
- id->kind = identification->get_type(identification);
-
- switch (id->kind)
- {
- case ID_FQDN:
- case ID_USER_FQDN:
- case ID_DER_ASN1_DN:
- case ID_KEY_ID:
- id->name = encoding;
- break;
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- initaddr(encoding.ptr, encoding.len,
- (id->kind == ID_IPV4_ADDR) ? AF_INET : AF_INET6,
- &id->ip_addr);
- break;
- case ID_ANY:
- default:
- id->kind = ID_ANY;
- id->name = chunk_empty;
- }
-}
-
-/*
- * Local Variables:
- * c-basic-offset:4
- * c-style: pluto
- * End:
- */
+++ /dev/null
-/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
- * Copyright (C) 1999-2001 D. Hugh Redelmeier
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- */
-
-#ifndef _ID_H
-#define _ID_H
-
-#include <utils/identification.h>
-
-#include "defs.h"
-
-struct id {
- int kind; /* ID_* value */
- ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */
- chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */
- /* ID_KEY_ID, ID_DER_ASN_DN */
-};
-
-extern void init_id(void);
-extern void free_id(void);
-extern const struct id empty_id; /* ID_ANY */
-
-enum myid_state {
- MYID_UNKNOWN, /* not yet figured out */
- MYID_HOSTNAME, /* our current hostname */
- MYID_IP, /* our default IP address */
- MYID_SPECIFIED /* as specified by ipsec.conf */
-};
-
-extern enum myid_state myid_state;
-extern struct id myids[MYID_SPECIFIED+1]; /* %myid */
-extern char *myid_str[MYID_SPECIFIED+1]; /* strings */
-extern void set_myid(enum myid_state s, char *);
-extern void show_myid_status(void);
-#define resolve_myid(id) ((id)->kind == ID_MYID? &myids[myid_state] : (id))
-extern void set_myFQDN(void);
-
-extern err_t atoid(char *src, struct id *id, bool myid_ok);
-extern int keyidtoa(char *dst, size_t dstlen, chunk_t keyid);
-extern void iptoid(const ip_address *ip, struct id *id);
-extern int idtoa(const struct id *id, char *dst, size_t dstlen);
-#define IDTOA_BUF 512
-extern void escape_metachar(const char *src, char *dst, size_t dstlen);
-struct end; /* forward declaration of tag (defined in connections.h) */
-extern void unshare_id_content(struct id *id);
-extern void free_id_content(struct id *id);
-extern bool same_id(const struct id *a, const struct id *b);
-#define MAX_WILDCARDS 15
-extern bool match_id(const struct id *a, const struct id *b, int *wildcards);
-extern int id_count_wildcards(const struct id *id);
-#define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
-
-struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */
-extern void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl,
- struct end *end);
-extern void id_from_identification(struct id *id, identification_t *identification);
-
-#endif /* _ID_H */
#include <crypto/rngs/rng.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
+#include <utils/identification.h>
#include "constants.h"
#include "defs.h"
+#include "myid.h"
#include "state.h"
-#include "id.h"
#include "x509.h"
+#include "ac.h"
#include "crl.h"
#include "ca.h"
#include "certs.h"
}
}
-static stf_status check_signature(key_type_t key_type, const struct id* peer,
+static stf_status check_signature(key_type_t key_type, identification_t* peer,
struct state *st, chunk_t hash,
const pb_stream *sig_pbs,
#ifdef USE_KEYRR
for (gw = c->gw_info; gw != NULL; gw = gw->next)
{
/* only consider entries that have a key and are for our peer */
- if (gw->gw_key_present && same_id(&gw->gw_id, &c->spd.that.id)&&
+ if (gw->gw_key_present &&
+ gw->gw_id->equals(gw->gw_id, c->spd.that.id) &&
take_a_crack(&s, gw->key))
{
return STF_OK;
{
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
- struct id key_id;
- id_from_identification(&key_id, key->id);
-
- if (type == key_type && same_id(peer, &key_id))
+ if (type == key_type && peer->equals(peer, key->id))
{
time_t now = time(NULL);
/* no acceptable key was found: diagnose */
{
- char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
-
- idtoa(peer, id_buf, sizeof(id_buf));
-
if (s.tried_cnt == 0)
{
- loglog(RC_LOG_SERIOUS, "no public key known for '%s'", id_buf);
+ loglog(RC_LOG_SERIOUS, "no public key known for '%Y'", peer);
}
else if (s.tried_cnt == 1)
{
- loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
- " wrong key?; tried %d", id_buf, s.tried_cnt);
+ loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
+ " wrong key?; tried %d", peer, s.tried_cnt);
DBG(DBG_CONTROL,
- DBG_log("public key for '%s' failed: "
- "decrypted SIG payload into a malformed ECB", id_buf)
+ DBG_log("public key for '%Y' failed: "
+ "decrypted SIG payload into a malformed ECB", peer)
)
}
else
{
- loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
- "tried %d keys but none worked.", id_buf, s.tried_cnt);
+ loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
+ "tried %d keys but none worked.", peer, s.tried_cnt);
DBG(DBG_CONTROL,
- DBG_log("all %d public keys for '%s' failed: "
+ DBG_log("all %d public keys for '%Y' failed: "
"best decrypted SIG payload into a malformed ECB",
- s.tried_cnt, id_buf)
+ s.tried_cnt, peer)
)
}
return STF_FAIL + INVALID_KEY_INFORMATION;
}
else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
{
- x509cert_t *x509cert = NULL;
+ linked_list_t *certs = linked_list_create();
- if (pkcs7_parse_signedData(blob, NULL, &x509cert, NULL, NULL))
+ if (pkcs7_parse_signedData(blob, NULL, certs, NULL, NULL))
{
- store_x509certs(&x509cert, strict_crl_policy);
+ store_x509certs(certs, strict_crl_policy);
}
else
{
plog("Syntax error in PKCS#7 wrapped X.509 certificates");
}
+ certs->destroy_offset(certs, offsetof(certificate_t, destroy));
}
else
{
* We must be called before SIG or HASH are decoded since we
* may change the peer's public key or ID.
*/
-static bool decode_peer_id(struct msg_digest *md, struct id *peer)
+static bool decode_peer_id(struct msg_digest *md, identification_t **peer)
{
struct state *const st = md->st;
struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID];
const pb_stream *const id_pbs = &id_pld->pbs;
struct isakmp_id *const id = &id_pld->payload.id;
+ chunk_t id_payload;
/* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
* It talks about the protocol ID and Port fields of the ID
return FALSE;
}
- peer->kind = id->isaid_idtype;
+ id_payload = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- switch (peer->kind)
+ switch (id->isaid_idtype)
{
- case ID_IPV4_ADDR:
- case ID_IPV6_ADDR:
- /* failure mode for initaddr is probably inappropriate address length */
- {
- err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs)
- , peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6
- , &peer->ip_addr);
-
- if (ugh != NULL)
+ case ID_IPV4_ADDR:
+ if (id_payload.len != 4)
{
- loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s"
- , enum_show(&ident_names, peer->kind), ugh);
- /* XXX Could send notification back */
+ loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
return FALSE;
}
- }
- break;
-
- case ID_USER_FQDN:
- if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL)
- {
- loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @");
- return FALSE;
- }
- /* FALLTHROUGH */
- case ID_FQDN:
- if (memchr(id_pbs->cur, '\0', pbs_left(id_pbs)) != NULL)
- {
- loglog(RC_LOG_SERIOUS, "Phase 1 ID Payload of type %s contains a NUL"
- , enum_show(&ident_names, peer->kind));
+ break;
+ case ID_IPV6_ADDR:
+ if (id_payload.len != 16)
+ {
+ loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
+ return FALSE;
+ }
+ break;
+ case ID_USER_FQDN:
+ case ID_FQDN:
+ if (memchr(id_payload.ptr, '\0', id_payload.len) != NULL)
+ {
+ loglog(RC_LOG_SERIOUS, "%s Phase 1 ID payload contains "
+ "a NUL character",
+ enum_show(&ident_names, id->isaid_idtype));
+ return FALSE;
+ }
+ break;
+ case ID_KEY_ID:
+ case ID_DER_ASN1_DN:
+ break;
+ default:
+ /* XXX Could send notification back */
+ loglog(RC_LOG_SERIOUS, "unacceptable identity type (%s) "
+ "in Phase 1 ID payload",
+ enum_show(&ident_names, id->isaid_idtype));
return FALSE;
- }
-
- /* ??? ought to do some more sanity check, but what? */
-
- peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- break;
-
- case ID_KEY_ID:
- peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- DBG(DBG_PARSING,
- DBG_dump_chunk("KEY ID:", peer->name));
- break;
-
- case ID_DER_ASN1_DN:
- peer->name = chunk_create(id_pbs->cur, pbs_left(id_pbs));
- DBG(DBG_PARSING,
- DBG_dump_chunk("DER ASN1 DN:", peer->name));
- break;
-
- default:
- /* XXX Could send notification back */
- loglog(RC_LOG_SERIOUS, "Unacceptable identity type (%s) in Phase 1 ID Payload"
- , enum_show(&ident_names, peer->kind));
- return FALSE;
}
+ *peer = identification_create_from_encoding(id->isaid_idtype, id_payload);
- {
- char buf[BUF_LEN];
-
- idtoa(peer, buf, sizeof(buf));
- plog("Peer ID is %s: '%s'",
- enum_show(&ident_names, id->isaid_idtype), buf);
- }
+ plog("Peer ID is %s: '%Y'", enum_show(&ident_names, id->isaid_idtype),
+ *peer);
/* check for certificates */
decode_cert(md);
* - if the initiation was explicit, we'd be ignoring user's intent
* - if opportunistic, we'll lose our HOLD info
*/
-static bool switch_connection(struct msg_digest *md, struct id *peer,
+static bool switch_connection(struct msg_digest *md, identification_t *peer,
bool initiator)
{
struct state *const st = md->st;
{
int pathlen;
- if (!same_id(&c->spd.that.id, peer))
+ if (!peer->equals(peer, c->spd.that.id))
{
- char expect[BUF_LEN]
- , found[BUF_LEN];
-
- idtoa(&c->spd.that.id, expect, sizeof(expect));
- idtoa(peer, found, sizeof(found));
- loglog(RC_LOG_SERIOUS
- , "we require peer to have ID '%s', but peer declares '%s'"
- , expect, found);
+ loglog(RC_LOG_SERIOUS,
+ "we require peer to have ID '%Y', but peer declares '%Y'",
+ c->spd.that.id, peer);
return FALSE;
}
if (r == NULL)
{
- char buf[BUF_LEN];
-
- idtoa(peer, buf, sizeof(buf));
- loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%s'", buf);
+ loglog(RC_LOG_SERIOUS, "no suitable connection for peer '%Y'", peer);
return FALSE;
}
}
else if (c->spd.that.has_id_wildcards)
{
- free_id_content(&c->spd.that.id);
- c->spd.that.id = *peer;
+ c->spd.that.id->destroy(c->spd.that.id);
+ c->spd.that.id = peer->clone(peer);
c->spd.that.has_id_wildcards = FALSE;
- unshare_id_content(&c->spd.that.id);
}
}
return TRUE;
{
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
- struct id key_id;
- id_from_identification(&key_id, key->id);
- if (type == KEY_RSA && same_id(&c->spd.that.id, &key_id) &&
+ if (type == KEY_RSA &&
+ c->spd.that.id->equals(c->spd.that.id, key->id) &&
key->until_time == UNDEFINED_TIME)
{
/* found a preloaded public key */
}
}
+/* build an ID payload
+ * Note: no memory is allocated for the body of the payload (tl->ptr).
+ * We assume it will end up being a pointer into a sufficiently
+ * stable datastructure. It only needs to last a short time.
+ */
+static void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
+{
+ identification_t *id = resolve_myid(end->id);
+
+ zero(hd);
+ hd->isaiid_idtype = id->get_type(id);
+
+ switch (id->get_type(id))
+ {
+ case ID_ANY:
+ hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
+ tl->len = addrbytesptr(&end->host_addr,
+ (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
+ break;
+ case ID_IPV4_ADDR:
+ case ID_IPV6_ADDR:
+ case ID_FQDN:
+ case ID_USER_FQDN:
+ case ID_DER_ASN1_DN:
+ case ID_KEY_ID:
+ *tl = id->get_encoding(id);
+ break;
+ default:
+ bad_case(id->get_type(id));
+ }
+}
+
/* State Transition Functions.
*
* The definition of state_microcode_table in demux.c is a good
/* Create an instance
* This is a rare case: wildcard peer ID but static peer IP address
*/
- c = rw_instantiate(c, &md->sender, md->sender_port, NULL, &c->spd.that.id);
+ c = rw_instantiate(c, &md->sender, md->sender_port, NULL, c->spd.that.id);
}
/* Set up state */
typedef stf_status (key_tail_fn)(struct msg_digest *md
, struct key_continuation *kc);
-static void report_key_dns_failure(struct id *id, err_t ugh)
+static void report_key_dns_failure(identification_t *id, err_t ugh)
{
- char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
-
- (void) idtoa(id, id_buf, sizeof(id_buf));
- loglog(RC_LOG_SERIOUS, "no RSA public key known for '%s'"
- "; DNS search for KEY failed (%s)", id_buf, ugh);
+ loglog(RC_LOG_SERIOUS, "no RSA public key known for '%Y'"
+ "; DNS search for KEY failed (%s)", id, ugh);
}
{
chunk_t hash = chunk_alloca(MAX_DIGEST_LEN);
struct state *st = md->st;
- struct id peer;
+ identification_t *peer;
stf_status r = STF_OK;
/* ID Payload in */
if (!decode_peer_id(md, &peer))
+ {
return STF_FAIL + INVALID_ID_INFORMATION;
+ }
/* Hash the ID Payload.
* main_mode_hash requires idpl->cur to be at end of payload
case OAKLEY_RSA_SIG:
case XAUTHInitRSA:
case XAUTHRespRSA:
- r = check_signature(KEY_RSA, &peer, st, hash,
- &md->chain[ISAKMP_NEXT_SIG]->pbs,
+ r = check_signature(KEY_RSA, peer, st, hash,
+ &md->chain[ISAKMP_NEXT_SIG]->pbs,
#ifdef USE_KEYRR
- kc == NULL? NULL : kc->ac.keys_from_dns,
+ kc == NULL ? NULL : kc->ac.keys_from_dns,
#endif /* USE_KEYRR */
- kc == NULL? NULL : kc->ac.gateways_from_dns
+ kc == NULL ? NULL : kc->ac.gateways_from_dns
);
if (r == STF_SUSPEND)
#ifdef USE_KEYRR
nkc->failure_ok = TRUE;
#endif
- ugh = start_adns_query(&peer
- , &peer /* SG itself */
- , T_TXT
- , cont_fn
- , &nkc->ac);
+ ugh = start_adns_query(peer, peer, T_TXT, cont_fn, &nkc->ac);
break;
#ifdef USE_KEYRR
case kos_his_txt:
/* second try: look for the KEY records */
nkc->step = kos_his_key;
- ugh = start_adns_query(&peer
- , NULL /* no sgw for KEY */
- , T_KEY
- , cont_fn
- , &nkc->ac);
+ ugh = start_adns_query(peer, NULL, T_KEY, cont_fn, &nkc->ac);
break;
#endif /* USE_KEYRR */
if (ugh != NULL)
{
- report_key_dns_failure(&peer, ugh);
+ report_key_dns_failure(peer, ugh);
st->st_suspended_md = NULL;
r = STF_FAIL + INVALID_KEY_INFORMATION;
}
case OAKLEY_ECDSA_256:
case OAKLEY_ECDSA_384:
case OAKLEY_ECDSA_521:
- r = check_signature(KEY_ECDSA, &peer, st, hash,
+ r = check_signature(KEY_ECDSA, peer, st, hash,
&md->chain[ISAKMP_NEXT_SIG]->pbs,
#ifdef USE_KEYRR
NULL,
}
if (r != STF_OK)
{
+ peer->destroy(peer);
return r;
}
DBG(DBG_CRYPT, DBG_log("authentication succeeded"));
/*
* With the peer ID known, let's see if we need to switch connections.
*/
- if (!switch_connection(md, &peer, initiator))
+ if (!switch_connection(md, peer, initiator))
{
- return STF_FAIL + INVALID_ID_INFORMATION;
+ r = STF_FAIL + INVALID_ID_INFORMATION;
}
+ peer->destroy(peer);
return r;
}
if (!kc->failure_ok && ugh != NULL)
{
- report_key_dns_failure(&st->st_connection->spd.that.id, ugh);
+ report_key_dns_failure(st->st_connection->spd.that.id, ugh);
r = STF_FAIL + INVALID_KEY_INFORMATION;
}
else
struct state *p1st = md->st;
connection_t *c = p1st->st_connection;
struct verify_oppo_continuation *vc = malloc_thing(struct verify_oppo_continuation);
- struct id id /* subject of query */
- , *our_id /* needed for myid playing */
- , our_id_space; /* ephemeral: no need for unshare_id_content */
+ identification_t *id; /* subject of query */
+ identification_t *our_id; /* needed for myid playing */
+ identification_t *our_id_space; /* ephemeral: no need for unshare_id_content */
ip_address client;
err_t ugh = NULL;
* %myid makes no sense for the other side (but it is syntactically
* legal).
*/
- our_id = resolve_myid(&c->spd.this.id);
- if (our_id->kind == ID_ANY)
+ our_id = resolve_myid(c->spd.this.id);
+ if (our_id->get_type(our_id) == ID_ANY)
{
- iptoid(&c->spd.this.host_addr, &our_id_space);
- our_id = &our_id_space;
+ our_id_space = identification_create_from_sockaddr((sockaddr_t*)&c->spd.this.host_addr);
+ our_id = our_id_space;
}
switch (next_step)
{
case vos_our_client:
networkof(&b->my.net, &client);
- iptoid(&client, &id);
+ id = identification_create_from_sockaddr((sockaddr_t*)&client);
vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
+ ugh = start_adns_query(id
, our_id
, T_TXT
, quick_inI1_outR1_continue
case vos_his_client:
networkof(&b->his.net, &client);
- iptoid(&client, &id);
+ id = identification_create_from_sockaddr((sockaddr_t*)&client);
vc->b.failure_ok = b->failure_ok = FALSE;
- ugh = start_adns_query(&id
- , &c->spd.that.id
+ ugh = start_adns_query(id
+ , c->spd.that.id
, T_TXT
, quick_inI1_outR1_continue
, &vc->ac);
* We should record DNS sec use, if any -- belongs in
* state during perhaps.
*/
- p = oppo_instantiate(p, &c->spd.that.host_addr, &c->spd.that.id
+ p = oppo_instantiate(p, &c->spd.that.host_addr, c->spd.that.id
, NULL, &our_client, &his_client);
}
else
* instantiate, carrying over authenticated peer ID
*/
p = rw_instantiate(p, &c->spd.that.host_addr, md->sender_port
- , his_net, &c->spd.that.id);
+ , his_net, c->spd.that.id);
}
}
#ifdef DEBUG
* for more details.
*/
+#ifndef _IPSEC_DOI_H
+#define _IPSEC_DOI_H
+
+#include "defs.h"
+
extern void echo_hdr(struct msg_digest *md, bool enc, u_int8_t np);
extern void ipsecdoi_initiate(int whack_sock, struct connection *c
} \
}
+#endif /* _IPSEC_DOI_H */
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "connections.h"
#include "state.h"
#include "timer.h"
return htonl((ipsec_spi_t)latest_cpi);
}
+/* Replace the shell metacharacters ', \, ", `, and $ in a character string
+ * by escape sequences consisting of their octal values
+ */
+static void escape_metachar(const char *src, char *dst, size_t dstlen)
+{
+ while (*src != '\0' && dstlen > 4)
+ {
+ switch (*src)
+ {
+ case '\'':
+ case '\\':
+ case '"':
+ case '`':
+ case '$':
+ sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
+ dst += 4;
+ dstlen -= 4;
+ break;
+ default:
+ *dst++ = *src;
+ dstlen--;
+ }
+ src++;
+ }
+ *dst = '\0';
+}
+
/* invoke the updown script to do the routing and firewall commands required
*
* The user-specified updown script is run. Parameters are fed to it in
}
addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
- idtoa(&sr->this.id, myid_str, sizeof(myid_str));
+ snprintf(myid_str, sizeof(myid_str), "%Y", sr->this.id);
escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));
networkof(&sr->this.client, &ta);
addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));
- idtoa(&sr->that.id, peerid_str, sizeof(peerid_str));
+ snprintf(peerid_str, sizeof(peerid_str), "%Y", sr->that.id);
escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));
subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
networkof(&sr->that.client, &ta);
{
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
- struct id key_id;
int pathlen;
- id_from_identification(&key_id, key->id);
-
- if (type == KEY_RSA && same_id(&sr->that.id, &key_id) &&
+ if (type == KEY_RSA &&
+ sr->that.id->equals(sr->that.id, key->id) &&
trusted_ca(key->issuer, sr->that.ca, &pathlen))
{
if (key->issuer)
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "x509.h"
#include "pgpcert.h"
#include "certs.h"
typedef struct id_list id_list_t;
struct id_list {
- struct id id;
+ identification_t *id;
id_list_t *next;
};
unsigned int best_match = 0;
secret_t *best = NULL;
secret_t *s;
- const struct id *my_id = &c->spd.this.id
- , *his_id = &c->spd.that.id;
- struct id rw_id;
+ identification_t *my_id, *his_id;
/* is there a certificate assigned to this connection? */
if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
return best;
}
+ my_id = c->spd.this.id;
+
if (his_id_was_instantiated(c))
{
/* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = c->spd.that.id.kind;
- rw_id.name = chunk_empty;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
+ his_id = identification_create_from_string("%any");
}
- else if (kind == PPK_PSK
- && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
- && ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_ANY) ||
- (c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
+ else if (kind == PPK_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) &&
+ ((c->kind == CK_TEMPLATE &&
+ c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) ||
+ (c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id))))
{
/* roadwarrior: replace him with 0.0.0.0 */
- rw_id.kind = ID_IPV4_ADDR;
- happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
- his_id = &rw_id;
+ his_id = identification_create_from_string("%any");
+ }
+ else
+ {
+ his_id = c->spd.that.id->clone(c->spd.that.id);
}
for (s = secrets; s != NULL; s = s->next)
for (i = s->ids; i != NULL; i = i->next)
{
- if (same_id(my_id, &i->id))
+ if (my_id->equals(my_id, i->id))
{
match |= match_me;
}
- if (same_id(his_id, &i->id))
+ if (his_id->equals(his_id, i->id))
{
match |= match_him;
}
}
}
}
+ his_id->destroy(his_id);
return best;
}
{
do
{
- n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
+ n += snprintf(buf + n, BUF_LEN - n, "%Y ", id_list->id);
if (n >= BUF_LEN)
{
n = BUF_LEN - 1;
break;
}
- else if (n < BUF_LEN - 1)
- {
- n += snprintf(buf + n, BUF_LEN - n, " ");
- }
id_list = id_list->next;
}
while (id_list);
/* an id
* See RFC2407 IPsec Domain of Interpretation 4.6.2
*/
- struct id id;
- err_t ugh;
-
- if (tokeq("%any"))
- {
- id = empty_id;
- id.kind = ID_IPV4_ADDR;
- ugh = anyaddr(AF_INET, &id.ip_addr);
- }
- else if (tokeq("%any6"))
- {
- id = empty_id;
- id.kind = ID_IPV6_ADDR;
- ugh = anyaddr(AF_INET6, &id.ip_addr);
- }
- else
- {
- ugh = atoid(tok, &id, FALSE);
- }
+ id_list_t *i = malloc_thing(id_list_t);
- if (ugh != NULL)
- {
- loglog(RC_LOG_SERIOUS
- , "ERROR \"%s\" line %d: index \"%s\" %s"
- , flp->filename, flp->lino, tok, ugh);
- }
- else
- {
- id_list_t *i = malloc_thing(id_list_t);
+ i->id = identification_create_from_string(tok);
+ i->next = s->ids;
+ s->ids = i;
- i->id = id;
- unshare_id_content(&i->id);
- i->next = s->ids;
- s->ids = i;
- /* DBG_log("id type %d: %s %.*s", i->kind, ip_str(&i->ip_addr), (int)i->name.len, i->name.ptr); */
- }
if (!shift())
{
/* unexpected Record Boundary or EOF */
{
id_list_t *i, *ni;
- ns = s->next; /* grab before freeing s */
+ ns = s->next;
for (i = s->ids; i != NULL; i = ni)
{
- ni = i->next; /* grab before freeing i */
- free_id_content(&i->id);
+ ni = i->next;
+ i->id->destroy(i->id);
free(i);
}
switch (s->kind)
#include "server.h"
#include "state.h"
#include "connections.h"
+#include "myid.h"
#include "kernel.h"
#include "whack.h" /* needs connections.h */
#include "timer.h"
peer.conn_name = st->st_connection->name;
addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
- idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id));
+ snprintf(peer.id, sizeof(peer.id), "%Y",
+ md->st->st_connection->spd.that.id);
DBG(DBG_CONTROL,
DBG_log("peer xauth user name is '%.*s'"
--- /dev/null
+/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
+ * Copyright (C) 1999-2001 D. Hugh Redelmeier
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#include <errno.h>
+#include <unistd.h>
+
+#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
+# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
+#endif
+
+#include <utils/identification.h>
+
+#include <freeswan.h>
+
+#include "myid.h"
+#include "constants.h"
+#include "defs.h"
+#include "log.h"
+#include "connections.h"
+#include "packet.h"
+#include "whack.h"
+
+enum myid_state myid_state = MYID_UNKNOWN;
+
+identification_t *myids[MYID_SPECIFIED+1]; /* %myid */
+
+/**
+ * Fills in myid from environment variable IPSECmyid or defaultrouteaddr
+ */
+void init_myid(void)
+{
+ myid_state = MYID_UNKNOWN;
+ {
+ enum myid_state s;
+
+ for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
+ {
+ myids[s] = identification_create_from_string("%any");
+ }
+ }
+ set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
+ set_myid(MYID_IP, getenv("defaultrouteaddr"));
+ set_myFQDN();
+}
+
+/**
+ * Free myid module
+ */
+void free_myid(void)
+{
+ enum myid_state s;
+
+ for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
+ {
+ myids[s]->destroy(myids[s]);
+ }
+}
+
+void set_myid(enum myid_state s, char *idstr)
+{
+ if (idstr)
+ {
+ myids[s]->destroy(myids[s]);
+ myids[s] = identification_create_from_string(idstr);
+ if (s == MYID_SPECIFIED)
+ {
+ myid_state = MYID_SPECIFIED;
+ }
+ }
+}
+
+void set_myFQDN(void)
+{
+ char FQDN[HOST_NAME_MAX + 1];
+ int r = gethostname(FQDN, sizeof(FQDN));
+ size_t len;
+
+ if (r != 0)
+ {
+ log_errno((e, "gethostname() failed in set_myFQDN"));
+ }
+ else
+ {
+ FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
+ len = strlen(FQDN);
+
+ if (len > 0 && FQDN[len-1] == '.')
+ {
+ /* nuke trailing . */
+ FQDN[len-1] = '\0';
+ }
+ if (!strcaseeq(FQDN, "localhost.localdomain"))
+ {
+ myids[MYID_HOSTNAME]->destroy(myids[MYID_HOSTNAME]);
+ myids[MYID_HOSTNAME] = identification_create_from_string(FQDN);
+ }
+ }
+}
+
+void show_myid_status(void)
+{
+ whack_log(RC_COMMENT, "%%myid = '%Y'", myids[myid_state]);
+}
+
+/*
+ * Local Variables:
+ * c-basic-offset:4
+ * c-style: pluto
+ * End:
+ */
--- /dev/null
+/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
+ * Copyright (C) 1999-2001 D. Hugh Redelmeier
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef _MYID_H
+#define _MYID_H
+
+#include <utils/identification.h>
+
+extern void init_myid(void);
+extern void free_myid(void);
+
+enum myid_state {
+ MYID_UNKNOWN, /* not yet figured out */
+ MYID_HOSTNAME, /* our current hostname */
+ MYID_IP, /* our default IP address */
+ MYID_SPECIFIED /* as specified by ipsec.conf */
+};
+
+extern enum myid_state myid_state;
+extern identification_t* myids[MYID_SPECIFIED+1]; /* %myid */
+extern void set_myid(enum myid_state s, char *);
+extern void show_myid_status(void);
+extern void set_myFQDN(void);
+
+#define resolve_myid(id) ((id)->get_type(id) == ID_MYID? myids[myid_state] : (id))
+
+#endif /* _MYID_H */
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "pgpcert.h"
#include "certs.h"
#include "whack.h"
#include "keys.h"
-
typedef enum pgp_packet_tag_t pgp_packet_tag_t;
/**
/**
* Select the OpenPGP keyid as ID
*/
-void select_pgpcert_id(pgpcert_t *cert, struct id *end_id)
+identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id)
{
- end_id->kind = ID_KEY_ID;
- end_id->name = cert->fingerprint->get_encoding(cert->fingerprint);
+ id->destroy(id);
+
+ return cert->fingerprint->clone(cert->fingerprint);
}
/**
#ifndef _PGPCERT_H
#define _PGPCERT_H
+#include <utils/identification.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
extern const pgpcert_t pgpcert_empty;
extern bool parse_pgp(chunk_t blob, pgpcert_t *cert);
extern void share_pgpcert(pgpcert_t *cert);
-extern void select_pgpcert_id(pgpcert_t *cert, struct id *end_id);
+extern identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
#include <string.h>
#include <time.h>
-#include <freeswan.h>
-
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
#include <asn1/oid.h>
#include <crypto/rngs/rng.h>
#include <crypto/crypters/crypter.h>
+#include <credentials/certificates/x509.h>
-#include "constants.h"
-#include "defs.h"
-#include "x509.h"
-#include "certs.h"
#include "pkcs7.h"
const contentInfo_t empty_contentInfo = {
/**
* Parse a PKCS#7 signedData object
*/
-bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert,
+bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
+ linked_list_t *certs,
chunk_t *attributes, certificate_t *cacert)
{
asn1_parser_t *parser;
}
break;
case PKCS7_SIGNED_CERT:
- if (cert != NULL)
{
- x509cert_t *newcert = malloc_thing(x509cert_t);
+ certificate_t *cert;
DBG2(" parsing pkcs7-wrapped certificate");
- *newcert = empty_x509cert;
- newcert->cert = lib->creds->create(lib->creds,
- CRED_CERTIFICATE, CERT_X509,
- BUILD_BLOB_ASN1_DER, object,
- BUILD_END);
- if (newcert->cert)
- {
- newcert->next = *cert;
- *cert = newcert;
- }
- else
+ cert = lib->creds->create(lib->creds,
+ CRED_CERTIFICATE, CERT_X509,
+ BUILD_BLOB_ASN1_DER, object,
+ BUILD_END);
+ if (cert)
{
- free_x509cert(newcert);
+ certs->insert_last(certs, cert);
}
}
break;
private_key_t *key)
{
contentInfo_t pkcs7Data, signedData;
- chunk_t authenticatedAttributes, encryptedDigest, signerInfo, cInfo;
+ chunk_t authenticatedAttributes = chunk_empty;
+ chunk_t encryptedDigest = chunk_empty;
+ chunk_t signerInfo, cInfo, signature;
+ signature_scheme_t scheme = signature_scheme_from_oid(digest_alg);
- if (attributes.ptr != NULL)
+ if (attributes.ptr)
{
- encryptedDigest = x509_build_signature(attributes, digest_alg, key,
- FALSE);
- authenticatedAttributes = chunk_clone(attributes);
- *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ if (key->sign(key, scheme, attributes, &signature))
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
+ authenticatedAttributes = chunk_clone(attributes);
+ *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
+ }
}
- else
+ else if (data.ptr)
{
- encryptedDigest = (data.ptr == NULL)? chunk_empty
- : x509_build_signature(data, digest_alg, key, FALSE);
- authenticatedAttributes = chunk_empty;
+ if (key->sign(key, scheme, data, &signature))
+ {
+ encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", signature);
+ }
}
-
signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm"
, ASN1_INTEGER_1
, pkcs7_build_issuerAndSerialNumber(cert)
#ifndef _PKCS7_H
#define _PKCS7_H
+#include <utils/linked_list.h>
#include <crypto/crypters/crypter.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
-#include "defs.h"
-#include "x509.h"
/* Access structure for a PKCS#7 ContentInfo object */
extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
contentInfo_t *cInfo);
extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
- x509cert_t **cert, chunk_t *attributes,
+ linked_list_t *cert, chunk_t *attributes,
certificate_t *cacert);
extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
chunk_t serialNumber, private_key_t *key);
#include "constants.h"
#include "defs.h"
-#include "id.h"
+#include "myid.h"
#include "ca.h"
#include "certs.h"
#include "ac.h"
init_demux();
init_kernel();
init_adns();
- init_id();
+ init_myid();
init_fetch();
/* drop unneeded capabilities and change UID/GID */
stop_adns();
free_md_pool();
free_crypto();
- free_id(); /* free myids */
+ free_myid(); /* free myids */
free_events(); /* free remaining events */
free_vendorid(); /* free all vendor id records */
free_builder();
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "ca.h"
#include "certs.h"
#include "ac.h"
#include "fetch.h"
#include "ocsp.h"
#include "crl.h"
-
+#include "myid.h"
#include "kernel_alg.h"
#include "ike_alg.h"
+
/* helper variables and function to decode strings from whack message */
static char *next_str
enum key_add_attempt lookingfor;
};
-static void key_add_ugh(const struct id *keyid, err_t ugh)
+static void key_add_ugh(identification_t *keyid, err_t ugh)
{
- char name[BUF_LEN]; /* longer IDs will be truncated in message */
-
- (void)idtoa(keyid, name, sizeof(name));
- loglog(RC_NOKEY
- , "failure to fetch key for %s from DNS: %s", name, ugh);
+ loglog(RC_NOKEY, "failure to fetch key for %'Y' from DNS: %s", keyid, ugh);
}
/* last one out: turn out the lights */
-static void key_add_merge(struct key_add_common *oc, const struct id *keyid)
+static void key_add_merge(struct key_add_common *oc, identification_t *keyid)
{
if (oc->refCount == 0)
{
/* if no success, print all diagnostics */
if (!oc->success)
+ {
for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ {
key_add_ugh(keyid, oc->diag[kaa]);
-
+ }
+ }
for (kaa = ka_TXT; kaa != ka_roof; kaa++)
{
free(oc->diag[kaa]);
}
oc->refCount--;
- key_add_merge(oc, &ac->id);
+ key_add_merge(oc, ac->id);
whack_log_fd = NULL_FD;
}
static void key_add_request(const whack_message_t *msg)
{
identification_t *key_id;
- struct id keyid;
- err_t ugh = atoid(msg->keyid, &keyid, FALSE);
- if (ugh != NULL)
+ key_id = identification_create_from_string(msg->keyid);
+
+ if (!msg->whack_addkey)
{
- loglog(RC_BADID, "bad --keyid \"%s\": %s", msg->keyid, ugh);
+ delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
}
- else
+ if (msg->keyval.len == 0)
{
- key_id = identification_create_from_string(msg->keyid);
+ struct key_add_common *oc = malloc_thing(struct key_add_common);
+ enum key_add_attempt kaa;
+ err_t ugh;
- if (!msg->whack_addkey)
- {
- delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
- }
- if (msg->keyval.len == 0)
+ /* initialize state shared by queries */
+ oc->refCount = 0;
+ oc->whack_fd = dup_any(whack_log_fd);
+ oc->success = FALSE;
+
+ for (kaa = ka_TXT; kaa != ka_roof; kaa++)
{
- struct key_add_common *oc = malloc_thing(struct key_add_common);
- enum key_add_attempt kaa;
+ struct key_add_continuation *kc;
- /* initialize state shared by queries */
- oc->refCount = 0;
- oc->whack_fd = dup_any(whack_log_fd);
- oc->success = FALSE;
+ oc->diag[kaa] = NULL;
+ oc->refCount++;
+ kc = malloc_thing(struct key_add_continuation);
+ kc->common = oc;
+ kc->lookingfor = kaa;
- for (kaa = ka_TXT; kaa != ka_roof; kaa++)
+ switch (kaa)
{
- struct key_add_continuation *kc;
-
- oc->diag[kaa] = NULL;
- oc->refCount++;
- kc = malloc_thing(struct key_add_continuation);
- kc->common = oc;
- kc->lookingfor = kaa;
-
- switch (kaa)
- {
case ka_TXT:
- ugh = start_adns_query(&keyid
- , &keyid /* same */
- , T_TXT
- , key_add_continue
- , &kc->ac);
+ ugh = start_adns_query(key_id
+ , key_id /* same */
+ , T_TXT
+ , key_add_continue
+ , &kc->ac);
break;
#ifdef USE_KEYRR
case ka_KEY:
- ugh = start_adns_query(&keyid
- , NULL
- , T_KEY
- , key_add_continue
- , &kc->ac);
+ ugh = start_adns_query(key_id
+ , NULL
+ , T_KEY
+ , key_add_continue
+ , &kc->ac);
break;
#endif /* USE_KEYRR */
default:
bad_case(kaa); /* suppress gcc warning */
- }
- if (ugh != NULL)
- {
- oc->diag[kaa] = clone_str(ugh);
- oc->refCount--;
- }
}
-
- /* Done launching queries.
- * Handle total failure case.
- */
- key_add_merge(oc, &keyid);
- }
- else
- {
- if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
- &pubkeys))
+ if (ugh)
{
- loglog(RC_LOG_SERIOUS, "failed to add public key");
+ oc->diag[kaa] = clone_str(ugh);
+ oc->refCount--;
}
}
- key_id->destroy(key_id);
+
+ /* Done launching queries. Handle total failure case. */
+ key_add_merge(oc, key_id);
+ }
+ else
+ {
+ if (!add_public_key(key_id, DAL_LOCAL, msg->pubkey_alg, msg->keyval,
+ &pubkeys))
+ {
+ loglog(RC_LOG_SERIOUS, "failed to add public key");
+ }
}
+ key_id->destroy(key_id);
}
/* Handle a kernel request. Supposedly, there's a message in
#include "constants.h"
#include "defs.h"
-#include "id.h"
#include "connections.h"
#include "state.h"
#include "packet.h"
if (get_preshared_secret(c) == NULL)
{
- char my_id[BUF_LEN], his_id[BUF_LEN];
+ char his_id[BUF_LEN];
- idtoa(&c->spd.this.id, my_id, sizeof(my_id));
if (his_id_was_instantiated(c))
{
strcpy(his_id, "%any");
}
else
{
- idtoa(&c->spd.that.id, his_id, sizeof(his_id));
+ snprintf(his_id, sizeof(his_id), "%Y", c->spd.that.id);
}
- ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
- , my_id, his_id);
+ ugh = builddiag("Can't authenticate: no preshared key found "
+ "for '%Y' and '%s'", c->spd.this.id, his_id);
}
return ugh;
}
#include <crypto/diffie_hellman.h>
+#include "defs.h"
#include "connections.h"
/* Message ID mechanism.
#include <freeswan.h>
#include <asn1/asn1.h>
-#include <asn1/asn1_parser.h>
-#include <asn1/oid.h>
#include <crypto/hashers/hasher.h>
#include <utils/enumerator.h>
#include <utils/identification.h>
#include "constants.h"
#include "defs.h"
#include "log.h"
-#include "id.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
*/
static x509cert_t *x509certs = NULL;
-/**
- * ASN.1 definition of a authorityKeyIdentifier extension
- */
-static const asn1Object_t authKeyIdentifierObjects[] = {
- { 0, "authorityKeyIdentifier", ASN1_SEQUENCE, ASN1_NONE }, /* 0 */
- { 1, "keyIdentifier", ASN1_CONTEXT_S_0, ASN1_OPT|ASN1_BODY }, /* 1 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 2 */
- { 1, "authorityCertIssuer", ASN1_CONTEXT_C_1, ASN1_OPT|ASN1_OBJ }, /* 3 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 4 */
- { 1, "authorityCertSerialNumber", ASN1_CONTEXT_S_2, ASN1_OPT|ASN1_BODY }, /* 5 */
- { 1, "end opt", ASN1_EOC, ASN1_END }, /* 6 */
- { 0, "exit", ASN1_EOC, ASN1_EXIT }
-};
-#define AUTH_KEY_ID_KEY_ID 1
-#define AUTH_KEY_ID_CERT_ISSUER 3
-#define AUTH_KEY_ID_CERT_SERIAL 5
-
const x509cert_t empty_x509cert = {
NULL , /* cert */
NULL , /* *next */
/* coding of X.501 distinguished name */
-typedef struct {
- const u_char *name;
- chunk_t oid;
- u_char type;
-} x501rdn_t;
-
-/* X.501 acronyms for well known object identifiers (OIDs) */
-
-static u_char oid_ND[] = {0x02, 0x82, 0x06, 0x01,
- 0x0A, 0x07, 0x14};
-static u_char oid_UID[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x01};
-static u_char oid_DC[] = {0x09, 0x92, 0x26, 0x89, 0x93,
- 0xF2, 0x2C, 0x64, 0x01, 0x19};
-static u_char oid_CN[] = {0x55, 0x04, 0x03};
-static u_char oid_S[] = {0x55, 0x04, 0x04};
-static u_char oid_SN[] = {0x55, 0x04, 0x05};
-static u_char oid_C[] = {0x55, 0x04, 0x06};
-static u_char oid_L[] = {0x55, 0x04, 0x07};
-static u_char oid_ST[] = {0x55, 0x04, 0x08};
-static u_char oid_O[] = {0x55, 0x04, 0x0A};
-static u_char oid_OU[] = {0x55, 0x04, 0x0B};
-static u_char oid_T[] = {0x55, 0x04, 0x0C};
-static u_char oid_D[] = {0x55, 0x04, 0x0D};
-static u_char oid_N[] = {0x55, 0x04, 0x29};
-static u_char oid_G[] = {0x55, 0x04, 0x2A};
-static u_char oid_I[] = {0x55, 0x04, 0x2B};
-static u_char oid_ID[] = {0x55, 0x04, 0x2D};
-static u_char oid_EN[] = {0x60, 0x86, 0x48, 0x01, 0x86,
- 0xF8, 0x42, 0x03, 0x01, 0x03};
-static u_char oid_E[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x01};
-static u_char oid_UN[] = {0x2A, 0x86, 0x48, 0x86, 0xF7,
- 0x0D, 0x01, 0x09, 0x02};
-static u_char oid_TCGID[] = {0x2B, 0x06, 0x01, 0x04, 0x01, 0x89,
- 0x31, 0x01, 0x01, 0x02, 0x02, 0x4B};
-
-static const x501rdn_t x501rdns[] = {
- {"ND" , {oid_ND, 7}, ASN1_PRINTABLESTRING},
- {"UID" , {oid_UID, 10}, ASN1_PRINTABLESTRING},
- {"DC" , {oid_DC, 10}, ASN1_PRINTABLESTRING},
- {"CN" , {oid_CN, 3}, ASN1_PRINTABLESTRING},
- {"S" , {oid_S, 3}, ASN1_PRINTABLESTRING},
- {"SN" , {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"serialNumber" , {oid_SN, 3}, ASN1_PRINTABLESTRING},
- {"C" , {oid_C, 3}, ASN1_PRINTABLESTRING},
- {"L" , {oid_L, 3}, ASN1_PRINTABLESTRING},
- {"ST" , {oid_ST, 3}, ASN1_PRINTABLESTRING},
- {"O" , {oid_O, 3}, ASN1_PRINTABLESTRING},
- {"OU" , {oid_OU, 3}, ASN1_PRINTABLESTRING},
- {"T" , {oid_T, 3}, ASN1_PRINTABLESTRING},
- {"D" , {oid_D, 3}, ASN1_PRINTABLESTRING},
- {"N" , {oid_N, 3}, ASN1_PRINTABLESTRING},
- {"G" , {oid_G, 3}, ASN1_PRINTABLESTRING},
- {"I" , {oid_I, 3}, ASN1_PRINTABLESTRING},
- {"ID" , {oid_ID, 3}, ASN1_PRINTABLESTRING},
- {"EN" , {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"employeeNumber" , {oid_EN, 10}, ASN1_PRINTABLESTRING},
- {"E" , {oid_E, 9}, ASN1_IA5STRING},
- {"Email" , {oid_E, 9}, ASN1_IA5STRING},
- {"emailAddress" , {oid_E, 9}, ASN1_IA5STRING},
- {"UN" , {oid_UN, 9}, ASN1_IA5STRING},
- {"unstructuredName", {oid_UN, 9}, ASN1_IA5STRING},
- {"TCGID" , {oid_TCGID, 12}, ASN1_PRINTABLESTRING}
-};
-
-#define X501_RDN_ROOF 26
-
-static void update_chunk(chunk_t *ch, int n)
-{
- n = (n > -1 && n < (int)ch->len)? n : (int)ch->len-1;
- ch->ptr += n; ch->len -= n;
-}
-
-/**
- * Pointer is set to the first RDN in a DN
- */
-static err_t init_rdn(chunk_t dn, chunk_t *rdn, chunk_t *attribute, bool *next)
-{
- *rdn = chunk_empty;
- *attribute = chunk_empty;
-
- /* a DN is a SEQUENCE OF RDNs */
-
- if (*dn.ptr != ASN1_SEQUENCE)
- {
- return "DN is not a SEQUENCE";
- }
-
- rdn->len = asn1_length(&dn);
-
- if (rdn->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid RDN length";
- }
- rdn->ptr = dn.ptr;
-
- /* are there any RDNs ? */
- *next = rdn->len > 0;
-
- return NULL;
-}
-
-/**
- * Fetches the next RDN in a DN
- */
-static err_t get_next_rdn(chunk_t *rdn, chunk_t * attribute, chunk_t *oid,
- chunk_t *value, asn1_t *type, bool *next)
-{
- chunk_t body;
-
- /* initialize return values */
- *oid = chunk_empty;
- *value = chunk_empty;
-
- /* if all attributes have been parsed, get next rdn */
- if (attribute->len <= 0)
- {
- /* an RDN is a SET OF attributeTypeAndValue */
- if (*rdn->ptr != ASN1_SET)
- {
- return "RDN is not a SET";
- }
- attribute->len = asn1_length(rdn);
-
- if (attribute->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid attribute length";
- }
- attribute->ptr = rdn->ptr;
-
- /* advance to start of next RDN */
- rdn->ptr += attribute->len;
- rdn->len -= attribute->len;
- }
-
- /* an attributeTypeAndValue is a SEQUENCE */
- if (*attribute->ptr != ASN1_SEQUENCE)
- {
- return "attributeTypeAndValue is not a SEQUENCE";
- }
-
- /* extract the attribute body */
- body.len = asn1_length(attribute);
-
- if (body.len == ASN1_INVALID_LENGTH)
- {
- return "Invalid attribute body length";
- }
- body.ptr = attribute->ptr;
-
- /* advance to start of next attribute */
- attribute->ptr += body.len;
- attribute->len -= body.len;
-
- /* attribute type is an OID */
- if (*body.ptr != ASN1_OID)
- {
- return "attributeType is not an OID";
- }
-
- /* extract OID */
- oid->len = asn1_length(&body);
-
- if (oid->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid attribute OID length";
- }
- oid->ptr = body.ptr;
-
- /* advance to the attribute value */
- body.ptr += oid->len;
- body.len -= oid->len;
-
- /* extract string type */
- *type = *body.ptr;
-
- /* extract string value */
- value->len = asn1_length(&body);
-
- if (value->len == ASN1_INVALID_LENGTH)
- {
- return "Invalid attribute string length";
- }
- value->ptr = body.ptr;
-
- /* are there any RDNs left? */
- *next = rdn->len > 0 || attribute->len > 0;
-
- return NULL;
-}
-
-/**
- * Prints a binary string in hexadecimal form
- */
-static void hex_str(chunk_t bin, chunk_t *str)
-{
- u_int i;
- update_chunk(str, snprintf(str->ptr,str->len,"0x"));
- for (i=0; i < bin.len; i++)
- update_chunk(str, snprintf(str->ptr,str->len,"%02X",*bin.ptr++));
-}
-
-/**
- * Parses an ASN.1 distinguished name int its OID/value pairs
- */
-static err_t dn_parse(chunk_t dn, chunk_t *str)
-{
- chunk_t rdn, oid, attribute, value;
- asn1_t type;
- int oid_code;
- bool next;
- bool first = TRUE;
-
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
-
- if (ugh) /* a parsing error has occured */
- {
- return ugh;
- }
-
- while (next)
- {
- ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
-
- if (ugh) /* a parsing error has occured */
- {
- return ugh;
- }
-
- if (first) /* first OID/value pair */
- {
- first = FALSE;
- }
- else /* separate OID/value pair by a comma */
- {
- update_chunk(str, snprintf(str->ptr,str->len,", "));
- }
-
- /* print OID */
- oid_code = asn1_known_oid(oid);
- if (oid_code == OID_UNKNOWN) /* OID not found in list */
- {
- hex_str(oid, str);
- }
- else
- {
- update_chunk(str, snprintf(str->ptr,str->len,"%s",
- oid_names[oid_code].name));
- }
-
- /* print value */
- update_chunk(str, snprintf(str->ptr,str->len,"=%.*s",
- (int)value.len,value.ptr));
- }
- return NULL;
-}
-
-/**
- * Count the number of wildcard RDNs in a distinguished name
- */
-int dn_count_wildcards(chunk_t dn)
-{
- chunk_t rdn, attribute, oid, value;
- asn1_t type;
- bool next;
- int wildcards = 0;
-
- err_t ugh = init_rdn(dn, &rdn, &attribute, &next);
-
- if (ugh) /* a parsing error has occured */
- {
- return -1;
- }
-
- while (next)
- {
- ugh = get_next_rdn(&rdn, &attribute, &oid, &value, &type, &next);
-
- if (ugh) /* a parsing error has occured */
- {
- return -1;
- }
- if (value.len == 1 && *value.ptr == '*')
- {
- wildcards++; /* we have found a wildcard RDN */
- }
- }
- return wildcards;
-}
-
-/** Converts a binary DER-encoded ASN.1 distinguished name
- * into LDAP-style human-readable ASCII format
- */
-int dntoa(char *dst, size_t dstlen, chunk_t dn)
-{
- err_t ugh = NULL;
- chunk_t str;
-
- str.ptr = dst;
- str.len = dstlen;
- ugh = dn_parse(dn, &str);
-
- if (ugh) /* error, print DN as hex string */
- {
- DBG(DBG_PARSING,
- DBG_log("error in DN parsing: %s", ugh)
- )
- str.ptr = dst;
- str.len = dstlen;
- hex_str(dn, &str);
- }
- return (int)(dstlen - str.len);
-}
-
-/**
- * Codes ASN.1 lengths up to a size of 16'777'215 bytes
- */
-static void code_asn1_length(size_t length, chunk_t *code)
-{
- if (length < 128)
- {
- code->ptr[0] = length;
- code->len = 1;
- }
- else if (length < 256)
- {
- code->ptr[0] = 0x81;
- code->ptr[1] = (u_char) length;
- code->len = 2;
- }
- else if (length < 65536)
- {
- code->ptr[0] = 0x82;
- code->ptr[1] = length >> 8;
- code->ptr[2] = length & 0x00ff;
- code->len = 3;
- }
- else
- {
- code->ptr[0] = 0x83;
- code->ptr[1] = length >> 16;
- code->ptr[2] = (length >> 8) & 0x00ff;
- code->ptr[3] = length & 0x0000ff;
- code->len = 4;
- }
-}
-
-/**
- * Converts an LDAP-style human-readable ASCII-encoded
- * ASN.1 distinguished name into binary DER-encoded format
- */
-err_t atodn(char *src, chunk_t *dn)
-{
- /* finite state machine for atodn */
-
- typedef enum {
- SEARCH_OID = 0,
- READ_OID = 1,
- SEARCH_NAME = 2,
- READ_NAME = 3,
- UNKNOWN_OID = 4
- } state_t;
-
- u_char oid_len_buf[3];
- u_char name_len_buf[3];
- u_char rdn_seq_len_buf[3];
- u_char rdn_set_len_buf[3];
- u_char dn_seq_len_buf[3];
-
- chunk_t asn1_oid_len = { oid_len_buf, 0 };
- chunk_t asn1_name_len = { name_len_buf, 0 };
- chunk_t asn1_rdn_seq_len = { rdn_seq_len_buf, 0 };
- chunk_t asn1_rdn_set_len = { rdn_set_len_buf, 0 };
- chunk_t asn1_dn_seq_len = { dn_seq_len_buf, 0 };
- chunk_t oid = chunk_empty;
- chunk_t name = chunk_empty;
-
- int whitespace = 0;
- int rdn_seq_len = 0;
- int rdn_set_len = 0;
- int dn_seq_len = 0;
- int pos = 0;
-
- err_t ugh = NULL;
-
- u_char *dn_ptr = dn->ptr + 4;
-
- state_t state = SEARCH_OID;
-
- do
- {
- switch (state)
- {
- case SEARCH_OID:
- if (*src != ' ' && *src != '/' && *src != ',')
- {
- oid.ptr = src;
- oid.len = 1;
- state = READ_OID;
- }
- break;
- case READ_OID:
- if (*src != ' ' && *src != '=')
- {
- oid.len++;
- }
- else
- {
- for (pos = 0; pos < X501_RDN_ROOF; pos++)
- {
- if (strlen(x501rdns[pos].name) == oid.len &&
- strncasecmp(x501rdns[pos].name, oid.ptr, oid.len) == 0)
- {
- break; /* found a valid OID */
- }
- }
- if (pos == X501_RDN_ROOF)
- {
- ugh = "unknown OID in distinguished name";
- state = UNKNOWN_OID;
- break;
- }
- code_asn1_length(x501rdns[pos].oid.len, &asn1_oid_len);
-
- /* reset oid and change state */
- oid = chunk_empty;
- state = SEARCH_NAME;
- }
- break;
- case SEARCH_NAME:
- if (*src != ' ' && *src != '=')
- {
- name.ptr = src;
- name.len = 1;
- whitespace = 0;
- state = READ_NAME;
- }
- break;
- case READ_NAME:
- if (*src != ',' && *src != '/' && *src != '\0')
- {
- name.len++;
- if (*src == ' ')
- {
- whitespace++;
- }
- else
- {
- whitespace = 0;
- }
- }
- else
- {
- name.len -= whitespace;
- code_asn1_length(name.len, &asn1_name_len);
-
- /* compute the length of the relative distinguished name sequence */
- rdn_seq_len = 1 + asn1_oid_len.len + x501rdns[pos].oid.len +
- 1 + asn1_name_len.len + name.len;
- code_asn1_length(rdn_seq_len, &asn1_rdn_seq_len);
-
- /* compute the length of the relative distinguished name set */
- rdn_set_len = 1 + asn1_rdn_seq_len.len + rdn_seq_len;
- code_asn1_length(rdn_set_len, &asn1_rdn_set_len);
-
- /* encode the relative distinguished name */
- *dn_ptr++ = ASN1_SET;
- chunkcpy(dn_ptr, asn1_rdn_set_len);
- *dn_ptr++ = ASN1_SEQUENCE;
- chunkcpy(dn_ptr, asn1_rdn_seq_len);
- *dn_ptr++ = ASN1_OID;
- chunkcpy(dn_ptr, asn1_oid_len);
- chunkcpy(dn_ptr, x501rdns[pos].oid);
- /* encode the ASN.1 character string type of the name */
- *dn_ptr++ = (x501rdns[pos].type == ASN1_PRINTABLESTRING
- && !asn1_is_printablestring(name))? ASN1_T61STRING : x501rdns[pos].type;
- chunkcpy(dn_ptr, asn1_name_len);
- chunkcpy(dn_ptr, name);
-
- /* accumulate the length of the distinguished name sequence */
- dn_seq_len += 1 + asn1_rdn_set_len.len + rdn_set_len;
-
- /* reset name and change state */
- name = chunk_empty;
- state = SEARCH_OID;
- }
- break;
- case UNKNOWN_OID:
- break;
- }
- } while (*src++ != '\0');
-
- /* complete the distinguished name sequence*/
- code_asn1_length(dn_seq_len, &asn1_dn_seq_len);
- dn->ptr += 3 - asn1_dn_seq_len.len;
- dn->len = 1 + asn1_dn_seq_len.len + dn_seq_len;
- dn_ptr = dn->ptr;
- *dn_ptr++ = ASN1_SEQUENCE;
- chunkcpy(dn_ptr, asn1_dn_seq_len);
- return ugh;
-}
-
-/**
- * compare two distinguished names by comparing the individual RDNs
- */
-bool same_dn(chunk_t a, chunk_t b)
-{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
-
- /* same lengths for the DNs */
- if (a.len != b.len)
- {
- return FALSE;
- }
-
- /* try a binary comparison first */
- if (memeq(a.ptr, b.ptr, b.len))
- {
- return TRUE;
- }
-
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
- || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
- {
- return FALSE;
- }
-
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
- || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
- {
- return FALSE;
- }
-
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- {
- return FALSE;
- }
-
- /* same lengths for values */
- if (value_a.len != value_b.len)
- {
- return FALSE;
- }
-
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_EMAIL_ADDRESS)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- else
- {
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- }
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- {
- return FALSE;
- }
-
- /* the two DNs are equal! */
- return TRUE;
-}
-
-
-/**
- * Compare two distinguished names by comparing the individual RDNs.
- * A single'*' character designates a wildcard RDN in DN b.
- */
-bool match_dn(chunk_t a, chunk_t b, int *wildcards)
-{
- chunk_t rdn_a, rdn_b, attribute_a, attribute_b;
- chunk_t oid_a, oid_b, value_a, value_b;
- asn1_t type_a, type_b;
- bool next_a, next_b;
-
- /* initialize wildcard counter */
- *wildcards = 0;
-
- /* initialize DN parsing */
- if (init_rdn(a, &rdn_a, &attribute_a, &next_a) != NULL
- || init_rdn(b, &rdn_b, &attribute_b, &next_b) != NULL)
- {
- return FALSE;
- }
-
- /* fetch next RDN pair */
- while (next_a && next_b)
- {
- /* parse next RDNs and check for errors */
- if (get_next_rdn(&rdn_a, &attribute_a, &oid_a, &value_a, &type_a, &next_a) != NULL
- || get_next_rdn(&rdn_b, &attribute_b, &oid_b, &value_b, &type_b, &next_b) != NULL)
- {
- return FALSE;
- }
-
- /* OIDs must agree */
- if (oid_a.len != oid_b.len || memcmp(oid_a.ptr, oid_b.ptr, oid_b.len) != 0)
- {
- return FALSE;
- }
-
- /* does rdn_b contain a wildcard? */
- if (value_b.len == 1 && *value_b.ptr == '*')
- {
- (*wildcards)++;
- continue;
- }
-
- /* same lengths for values */
- if (value_a.len != value_b.len)
- {
- return FALSE;
- }
-
- /* printableStrings and email RDNs require uppercase comparison */
- if (type_a == type_b && (type_a == ASN1_PRINTABLESTRING ||
- (type_a == ASN1_IA5STRING && asn1_known_oid(oid_a) == OID_EMAIL_ADDRESS)))
- {
- if (strncasecmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- else
- {
- if (strncmp(value_a.ptr, value_b.ptr, value_b.len) != 0)
- {
- return FALSE;
- }
- }
- }
-
- /* both DNs must have same number of RDNs */
- if (next_a || next_b)
- {
- return FALSE;
- }
-
- /* the two DNs match! */
- return TRUE;
-}
-
/**
* For each link pointing to the certificate increase the count by one
*/
/**
* Choose either subject DN or a subjectAltName as connection end ID
*/
-void select_x509cert_id(x509cert_t *cert, struct id *end_id)
+identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id)
{
certificate_t *certificate = cert->cert;
x509_t *x509 = (x509_t*)certificate;
- identification_t *subjectAltName;
+ identification_t *subject, *subjectAltName;
- bool copy_subject_dn = TRUE; /* ID is subject DN */
+ bool copy_subject_dn = TRUE; /* ID is subject DN */
- if (end_id->kind != ID_ANY) /* check for matching subjectAltName */
+ if (id->get_type(id) != ID_ANY) /* check for a matching subjectAltName */
{
enumerator_t *enumerator;
enumerator = x509->create_subjectAltName_enumerator(x509);
while (enumerator->enumerate(enumerator, &subjectAltName))
{
- struct id id = empty_id;
-
- id_from_identification(&id, subjectAltName);
- if (same_id(&id, end_id))
+ if (id->equals(id, subjectAltName))
{
copy_subject_dn = FALSE; /* take subjectAltName instead */
break;
}
enumerator->destroy(enumerator);
}
-
if (copy_subject_dn)
{
- identification_t *subject = certificate->get_subject(certificate);
- chunk_t subject_dn = subject->get_encoding(subject);
+ id->destroy(id);
+ subject = certificate->get_subject(certificate);
+ plog(" no subjectAltName matches ID '%Y', replaced by subject DN", id);
- if (end_id->kind != ID_ANY && end_id->kind != ID_DER_ASN1_DN)
- {
- char buf[BUF_LEN];
-
- idtoa(end_id, buf, BUF_LEN);
- plog(" no subjectAltName matches ID '%s', replaced by subject DN", buf);
- }
- end_id->kind = ID_DER_ASN1_DN;
- end_id->name.len = subject_dn.len;
- end_id->name.ptr = temporary_cyclic_buffer();
- memcpy(end_id->name.ptr, subject_dn.ptr, subject_dn.len);
+ return subject->clone(subject);
+ }
+ else
+ {
+ return id;
}
}
/**
* Stores a chained list of end certs and CA certs
*/
-void store_x509certs(x509cert_t **firstcert, bool strict)
+void store_x509certs(linked_list_t *certs, bool strict)
{
- x509cert_t *cacerts = NULL;
- x509cert_t **pp = firstcert;
+ x509cert_t *x509cert, *cacerts = NULL;
+ certificate_t *cert;
+ enumerator_t *enumerator;
- /* first extract CA certs, discarding root CA certs */
+ /* first extract CA certs, ignoring self-signed root CA certs */
- while (*pp)
+ enumerator = certs->create_enumerator(certs);
+ while (enumerator->enumerate(enumerator, &cert))
{
- x509cert_t *cert = *pp;
- certificate_t *certificate = cert->cert;
- x509_t *x509 = (x509_t*)certificate;
- x509_flag_t flags = x509->get_flags(x509);
+ x509_t *x509 = (x509_t*)cert;
+ x509_flag_t flags;
+ flags = x509->get_flags(x509);
if (flags & X509_CA)
{
- *pp = cert->next;
-
/* we don't accept self-signed CA certs */
if (flags & X509_SELF_SIGNED)
{
plog("self-signed cacert rejected");
- free_x509cert(cert);
}
else
{
/* insertion into temporary chain of candidate CA certs */
- cert->next = cacerts;
- cacerts = cert;
+ x509cert = malloc_thing(x509cert_t);
+ *x509cert = empty_x509cert;
+ x509cert->cert = cert->get_ref(cert);
+ x509cert->next = cacerts;
+ cacerts = x509cert;
}
}
- else
- {
- pp = &cert->next;
- }
}
+ enumerator->destroy(enumerator);
/* now verify the candidate CA certs */
/* now verify the end certificates */
- pp = firstcert;
-
- while (*pp)
+ enumerator = certs->create_enumerator(certs);
+ while (enumerator->enumerate(enumerator, &cert))
{
time_t valid_until;
- x509cert_t *cert = *pp;
+ x509_t *x509 = (x509_t*)cert;
- if (verify_x509cert(cert, strict, &valid_until))
+ if (!(x509->get_flags(x509) & X509_CA))
{
- DBG(DBG_CONTROL | DBG_PARSING,
- DBG_log("public key validated")
- )
- add_x509_public_key(cert, valid_until, DAL_SIGNED);
- }
- else
- {
- plog("X.509 certificate rejected");
+ x509cert = malloc_thing(x509cert_t);
+ *x509cert = empty_x509cert;
+ x509cert->cert = cert->get_ref(cert);
+
+ if (verify_x509cert(x509cert, strict, &valid_until))
+ {
+ DBG(DBG_CONTROL | DBG_PARSING,
+ DBG_log("public key validated")
+ )
+ add_x509_public_key(x509cert, valid_until, DAL_SIGNED);
+ }
+ else
+ {
+ plog("X.509 certificate rejected");
+ free_x509cert(x509cert);
+ }
}
- *pp = cert->next;
- free_x509cert(cert);
}
+ enumerator->destroy(enumerator);
}
/**
#define _X509_H
#include <utils/identification.h>
+#include <utils/linked_list.h>
#include <credentials/keys/public_key.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/x509.h>
#include "constants.h"
-#include "id.h"
/* access structure for an X.509v3 certificate */
extern const x509cert_t empty_x509cert;
extern bool same_keyid(chunk_t a, chunk_t b);
-extern bool same_dn(chunk_t a, chunk_t b);
-extern bool match_dn(chunk_t a, chunk_t b, int *wildcards);
-extern int dn_count_wildcards(chunk_t dn);
-extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
-extern err_t atodn(char *src, chunk_t *dn);
-extern void select_x509cert_id(x509cert_t *cert, struct id *end_id);
+extern identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0,
chunk_t *authKeyID,
chunk_t *authKeySerialNumber);
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
-extern void store_x509certs(x509cert_t **firstcert, bool strict);
+extern void store_x509certs(linked_list_t *certs, bool strict);
extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
x509_flag_t flags, bool utc);
extern void list_x509_end_certs(bool utc);
LIBFREESWANBUILDDIR=$(top_builddir)/src/libfreeswan
scepclient_LDADD = \
-ca.o crl.o certs.o constants.o defs.o fetch.o id.o keys.o lex.o \
-ocsp.o pgpcert.o pkcs7.o smartcard.o x509.o \
+constants.o defs.o lex.o pkcs7.o \
$(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
$(LIBFREESWANBUILDDIR)/libfreeswan.a
dist_man_MANS = scepclient.8
-ca.o : $(PLUTODIR)/ca.c $(PLUTODIR)/ca.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-certs.o : $(PLUTODIR)/certs.c $(PLUTODIR)/certs.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
-crl.o : $(PLUTODIR)/crl.c $(PLUTODIR)/crl.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
-fetch.o : $(PLUTODIR)/fetch.c $(PLUTODIR)/fetch.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-id.o : $(PLUTODIR)/id.c $(PLUTODIR)/id.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-keys.o : $(PLUTODIR)/keys.c $(PLUTODIR)/keys.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
-ocsp.o : $(PLUTODIR)/ocsp.c $(PLUTODIR)/ocsp.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-pgpcert.o : $(PLUTODIR)/pgpcert.c $(PLUTODIR)/pgpcert.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
-smartcard.o : $(PLUTODIR)/smartcard.c $(PLUTODIR)/smartcard.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
-
-x509.o : $(PLUTODIR)/x509.c $(PLUTODIR)/x509.h
- $(COMPILE) $(INCLUDES) -c -o $@ $<
#include "../pluto/constants.h"
#include "../pluto/defs.h"
#include "../pluto/log.h"
-#include "../pluto/pkcs7.h"
#include "../pluto/certs.h"
+#include "../pluto/pkcs7.h"
#include "scep.h"
*/
if (filetype_in & PKCS1) /* load an RSA key pair from file */
{
- prompt_pass_t pass = { "", FALSE, STDIN_FILENO };
char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1);
- private_key = load_private_key(path, &pass, KEY_RSA);
+ private_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
+ BUILD_FROM_FILE, path, BUILD_END);
}
else /* generate an RSA key pair */
{
*/
if (filetype_out & CERT)
{
+ certificate_t *cert;
+ enumerator_t *enumerator;
char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig);
time_t poll_start = 0;
- x509cert_t *certs = NULL;
+ linked_list_t *certs = linked_list_create();
chunk_t envelopedData = chunk_empty;
chunk_t certData = chunk_empty;
contentInfo_t data = empty_contentInfo;
{
exit_scepclient("could not decrypt envelopedData");
}
- if (!pkcs7_parse_signedData(certData, NULL, &certs, NULL, NULL))
+ if (!pkcs7_parse_signedData(certData, NULL, certs, NULL, NULL))
{
exit_scepclient("error parsing the scep response");
}
/* store the end entity certificate */
path = concatenate_paths(HOST_CERT_PATH, file_out_cert);
- while (certs != NULL)
+
+ enumerator = certs->create_enumerator(certs);
+ while (enumerator->enumerate(enumerator, &cert))
{
bool stored = FALSE;
- x509cert_t *cert = certs;
- x509_t *x509 = (x509_t*)cert->cert;
+ x509_t *x509 = (x509_t*)cert;
if (!(x509->get_flags(x509) & X509_CA))
{
{
exit_scepclient("multiple certs received, only first stored");
}
- encoding = cert->cert->get_encoding(cert->cert);
+ encoding = cert->get_encoding(cert);
if (!chunk_write(encoding, path, "requested cert", 0022, force))
{
exit_scepclient("could not write cert file '%s'", path);
chunk_free(&encoding);
stored = TRUE;
}
- certs = certs->next;
- free_x509cert(cert);
}
+ certs->destroy_offset(certs, offsetof(certificate_t, destroy));
filetype_out &= ~CERT; /* delete CERT flag */
}
#include <freeswan.h>
+#include <defs.h>
+
/* copy of smartcard operations, defined in smartcard.h */
#ifndef SC_OP_T
#define SC_OP_T