]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
replaced struct id by identification_t
authorAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 10 Oct 2009 19:16:46 +0000 (21:16 +0200)
committerAndreas Steffen <andreas.steffen@strongswan.org>
Sat, 10 Oct 2009 19:19:38 +0000 (21:19 +0200)
32 files changed:
src/pluto/Makefile.am
src/pluto/alg_info.c
src/pluto/builder.c
src/pluto/certs.c
src/pluto/connections.c
src/pluto/connections.h
src/pluto/dnskey.c
src/pluto/dnskey.h
src/pluto/fetch.c
src/pluto/id.c [deleted file]
src/pluto/id.h [deleted file]
src/pluto/ipsec_doi.c
src/pluto/ipsec_doi.h
src/pluto/kernel.c
src/pluto/keys.c
src/pluto/log.c
src/pluto/modecfg.c
src/pluto/myid.c [new file with mode: 0644]
src/pluto/myid.h [new file with mode: 0644]
src/pluto/pgpcert.c
src/pluto/pgpcert.h
src/pluto/pkcs7.c
src/pluto/pkcs7.h
src/pluto/plutomain.c
src/pluto/rcv_whack.c
src/pluto/spdb.c
src/pluto/state.h
src/pluto/x509.c
src/pluto/x509.h
src/scepclient/Makefile.am
src/scepclient/scepclient.c
src/whack/whack.h

index b481a50a9c3d45982d00aed4b84ef29f2c92fef9..e966299c016bba180ccd6a1321af3dca62df985f 100644 (file)
@@ -20,7 +20,6 @@ demux.c demux.h \
 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 \
@@ -32,6 +31,7 @@ kernel_pfkey.c kernel_pfkey.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 \
index 1cc2d189e16946b86d29c87cfb2098c149453f04..a9a6dd5f0a171f681ee98e4fbd957f69b8f77ea4 100644 (file)
@@ -461,12 +461,16 @@ struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
        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)
@@ -481,12 +485,16 @@ 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;
 }
 
 /*
index 004145103aa2e3baecb979c4fa275e976fdedea6..39a85eddb83378d01b8755f4f6ba77ce5dd1ec03 100644 (file)
@@ -30,7 +30,6 @@
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
-#include "id.h"
 #include "certs.h"
 #include "ac.h"
 #include "crl.h"
index 456a45fca3a2c68c1ed2a995b5d03876779210af..89e289b6ca4680f2e84f736883b042ac5bb7d1c9 100644 (file)
@@ -28,7 +28,6 @@
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
-#include "id.h"
 #include "certs.h"
 #include "whack.h"
 #include "builder.h"
@@ -228,10 +227,9 @@ void share_cert(cert_t cert)
 }
 
 /*  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)
        {
@@ -246,11 +244,10 @@ release_cert(cert_t cert)
        }
 }
 
-/*
+/**
  *  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);
index 01a80a10062eb64f18a9dc1325f8d107c1a613b3..a1cf2103e66c719ab2e4dc26743130665a88867c 100644 (file)
@@ -35,7 +35,7 @@
 
 #include "constants.h"
 #include "defs.h"
-#include "id.h"
+#include "myid.h"
 #include "x509.h"
 #include "ca.h"
 #include "crl.h"
@@ -92,12 +92,40 @@ static struct host_pair *host_pairs = NULL;
 
 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,
@@ -126,7 +154,7 @@ 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 */
@@ -223,7 +251,7 @@ connection_t *con_by_name(const char *nm, bool strict)
                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 */
@@ -334,14 +362,14 @@ void delete_connection(connection_t *c, bool relations)
        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,
@@ -373,8 +401,10 @@ void delete_connections_by_name(const char *name, bool strict)
 
 void delete_every_connection(void)
 {
-       while (connections != NULL)
+       while (connections)
+       {
                delete_connection(connections, TRUE);
+       }
 }
 
 void release_dead_interfaces(void)
@@ -434,7 +464,7 @@ void check_orientations(void)
 
                unoriented_connections = NULL;
 
-               while (c != NULL)
+               while (c)
                {
                        connection_t *nxt = c->hp_next;
 
@@ -473,7 +503,7 @@ void check_orientations(void)
                                                connection_t *c = hp->connections;
 
                                                hp->connections = NULL;
-                                               while (c != NULL)
+                                               while (c)
                                                {
                                                        connection_t *nxt = c->hp_next;
 
@@ -492,30 +522,35 @@ void check_orientations(void)
 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;
 }
 
@@ -616,25 +651,13 @@ size_t format_end(char *buf, size_t buf_len, const struct end *this,
                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 = "---";
@@ -673,8 +696,7 @@ static size_t format_connection(char *buf, size_t buf_len,
 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);
@@ -682,7 +704,11 @@ static void unshare_connection_strings(connection_t *c)
        {
                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);
@@ -690,6 +716,10 @@ static void unshare_connection_strings(connection_t *c)
        {
                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);
@@ -710,7 +740,7 @@ static void load_end_certificate(char *filename, struct end *dst)
        /* initialize smartcard info record */
        dst->sc = NULL;
 
-       if (filename != NULL)
+       if (filename)
        {
                if (scx_on_smartcard(filename))
                {
@@ -729,10 +759,12 @@ static void load_end_certificate(char *filename, struct end *dst)
                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;
@@ -742,7 +774,7 @@ static void load_end_certificate(char *filename, struct end *dst)
                        }
                        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)
                        {
@@ -779,7 +811,7 @@ static void load_end_certificate(char *filename, struct end *dst)
                }
 
                /* 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))
                        {
@@ -792,6 +824,8 @@ static void load_end_certificate(char *filename, struct end *dst)
                        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,
@@ -799,22 +833,7 @@ 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 */
@@ -840,7 +859,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
        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)
@@ -864,7 +883,7 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
        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
@@ -877,10 +896,14 @@ static bool extract_end(struct end *dst, const whack_end_t *src,
        {
                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;
 }
@@ -974,7 +997,7 @@ void add_connection(const whack_message_t *wm)
                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;
 
@@ -988,7 +1011,7 @@ void add_connection(const whack_message_t *wm)
                         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>";
@@ -1057,9 +1080,13 @@ void add_connection(const whack_message_t *wm)
                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);
@@ -1125,16 +1152,17 @@ void add_connection(const whack_message_t *wm)
                                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);
 
@@ -1249,12 +1277,10 @@ void remove_group_instance(const connection_t *group USED_BY_DEBUG,
  *
  * 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);
@@ -1263,10 +1289,9 @@ static connection_t *instantiate(connection_t *c,
        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);
@@ -1320,7 +1345,7 @@ static connection_t *instantiate(connection_t *c,
 
 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);
 
@@ -1346,7 +1371,7 @@ connection_t *rw_instantiate(connection_t *c, const ip_address *him,
 }
 
 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)
 {
@@ -1404,7 +1429,7 @@ connection_t *oppo_instantiate(connection_t *c, const ip_address *him,
                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);
@@ -1416,10 +1441,14 @@ connection_t *oppo_instantiate(connection_t *c, const ip_address *him,
 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.
@@ -1601,11 +1630,14 @@ connection_t *find_connection_for_clients(struct spd_route **srp,
                }
        }
 
-       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))
@@ -1662,12 +1694,6 @@ connection_t *build_outgoing_opportunistic_connection(struct gw_info *gw,
        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)
        {
@@ -1718,14 +1744,22 @@ connection_t *build_outgoing_opportunistic_connection(struct gw_info *gw,
                }
        }
 
-       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)
@@ -1796,7 +1830,7 @@ void initiate_connection(const char *name, int whackfd)
 {
        connection_t *c = con_by_name(name, TRUE);
 
-       if (c != NULL && c->ikev1)
+       if (c && c->ikev1)
        {
                set_cur_connection(c);
                if (!oriented(*c))
@@ -1818,11 +1852,11 @@ void initiate_connection(const char *name, int whackfd)
                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");
                        }
@@ -1831,8 +1865,8 @@ void initiate_connection(const char *name, int whackfd)
 
                                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
@@ -1938,7 +1972,7 @@ static void cannot_oppo(connection_t *c, struct find_oppo_bundle *b, err_t ugh)
                , "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;
@@ -2083,7 +2117,7 @@ static void continue_oppo(struct adns_continuation *acr, err_t ugh)
 
 #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,
                        {
@@ -2098,7 +2132,7 @@ static void continue_oppo(struct adns_continuation *acr, err_t ugh)
        }
 #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);
@@ -2180,8 +2214,10 @@ static err_t check_key_recs(enum myid_state try_state, const connection_t *c,
                        }
                }
        }
-       if (ugh != NULL)
+       if (ugh)
+       {
                myid_state = old_myid_state;
+       }
        return ugh;
 }
 #endif /* USE_KEYRR */
@@ -2211,7 +2247,7 @@ static err_t check_txt_recs(enum myid_state try_state, const connection_t *c,
        {
                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";
        }
@@ -2236,7 +2272,7 @@ static err_t check_txt_recs(enum myid_state try_state, const connection_t *c,
                        }
                }
        }
-       if (ugh != NULL)
+       if (ugh)
        {
                myid_state = old_myid_state;
        }
@@ -2337,17 +2373,11 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                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:
@@ -2357,18 +2387,17 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
 
                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;
                                }
 
@@ -2380,9 +2409,9 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                /* 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;
                                }
 
@@ -2392,18 +2421,17 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
 
                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
@@ -2416,9 +2444,9 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                /* 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;
@@ -2428,18 +2456,17 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
 #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;
                                }
 
@@ -2451,9 +2478,9 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                /* 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;
@@ -2462,21 +2489,19 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
 
                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 */
                        }
@@ -2485,9 +2510,9 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                /* 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;
@@ -2506,8 +2531,6 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
 
                                next_step = fos_his_client;     /* normal situation */
 
-                               passert(sr != NULL);
-
                                if (private == NULL)
                                {
                                        ugh = "we don't know our own RSA key";
@@ -2517,7 +2540,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        /* 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";
@@ -2532,8 +2555,6 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        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.
@@ -2576,7 +2597,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                {
                                        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";
                                }
@@ -2590,8 +2611,6 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        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))
@@ -2604,7 +2623,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                                }
                                        }
 #ifdef USE_KEYRR
-                                       if (ugh != NULL)
+                                       if (ugh)
                                        {
                                                /* if no TXT with right key, try KEY */
                                                DBG(DBG_CONTROL,
@@ -2691,18 +2710,14 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        /* 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)
@@ -2758,7 +2773,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        , 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);
@@ -2772,7 +2787,7 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                {
                        /* 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);
@@ -2813,23 +2828,20 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                        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
@@ -2838,11 +2850,9 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                        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;
                                }
 
@@ -2856,11 +2866,8 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                {
                                        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;
@@ -2872,11 +2879,8 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                {
                                        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
@@ -2890,12 +2894,10 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                         * 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;
@@ -2904,22 +2906,16 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                        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 */
 
@@ -2927,12 +2923,10 @@ static void initiate_opportunistic_body(struct find_oppo_bundle *b,
                                /* 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:
@@ -2976,7 +2970,7 @@ void terminate_connection(const char *nm)
                        reset_cur_connection();
                }
                c = n;
-       } while (c != NULL);
+       } while (c);
 }
 
 /* an ISAKMP SA has been established.
@@ -3006,10 +3000,10 @@ void ISAKMP_SA_established(connection_t *c, so_serial_t serial)
                {
                        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);
                        }
@@ -3114,7 +3108,7 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp,
                                        , (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))
@@ -3131,14 +3125,17 @@ connection_t *route_owner(connection_t *c, struct spd_route **srp,
                        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;
@@ -3183,7 +3180,7 @@ connection_t *find_host_connection(const ip_address *me, u_int16_t my_port,
                /* if we have requirements for the policy,
                 * choose the first matching connection.
                 */
-               while (c != NULL)
+               while (c)
                {
                        if (c->policy & auth_requested)
                        {
@@ -3257,7 +3254,7 @@ connection_t *find_host_connection(const ip_address *me, u_int16_t my_port,
 #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;
@@ -3268,13 +3265,13 @@ connection_t *refine_host_connection(const struct state *st,
        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"
@@ -3335,8 +3332,10 @@ connection_t *refine_host_connection(const struct state *st,
                {
                        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
@@ -3345,7 +3344,8 @@ connection_t *refine_host_connection(const struct state *st,
                                                                                , 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;
@@ -3458,7 +3458,7 @@ connection_t *refine_host_connection(const struct state *st,
  * 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;
 
@@ -3470,16 +3470,15 @@ static bool is_virtual_net_used(const ip_subnet *peer_net,
                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;
@@ -3518,11 +3517,11 @@ static bool is_virtual_net_used(const ip_subnet *peer_net,
 
 #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,
@@ -3535,7 +3534,9 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
        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);
 
@@ -3548,10 +3549,12 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
                        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;
                }
@@ -3620,7 +3623,7 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
                                        }
                                        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;
                                        }
@@ -3643,7 +3646,7 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
                         * - 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)
@@ -3654,9 +3657,10 @@ static connection_t *fc_try(const connection_t *c, struct host_pair *hp,
                }
        }
 
-       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)
@@ -3678,7 +3682,8 @@ static connection_t *fc_try_oppo(const connection_t *c,
        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)
        {
@@ -3689,10 +3694,12 @@ static connection_t *fc_try_oppo(const connection_t *c,
                {
                        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;
                }
@@ -3745,7 +3752,7 @@ static connection_t *fc_try_oppo(const connection_t *c,
                         * - 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)
                        {
@@ -3756,9 +3763,8 @@ static connection_t *fc_try_oppo(const connection_t *c,
        }
 
        /* 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;
        }
@@ -3922,7 +3928,7 @@ connection_t *find_client_connection(connection_t *c,
 #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
@@ -3959,12 +3965,16 @@ int connection_compare(const connection_t *ca, const connection_t *cb)
        /* 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)
@@ -4028,11 +4038,11 @@ void show_connections_status(bool all, const char *name)
 
                /* 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"
@@ -4065,7 +4075,7 @@ void show_connections_status(bool all, const char *name)
                        }
 
                        /* 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
@@ -4158,7 +4168,7 @@ void add_pending(int whack_sock, struct state *isakmp_sa, connection_t *c,
        bool already_queued = FALSE;
        struct pending *p = c->host_pair->pending;
 
-       while (p != NULL)
+       while (p)
        {
                if (streq(c->name, p->connection->name))
                {
@@ -4228,8 +4238,10 @@ static void delete_pending(struct pending **pp)
        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);
 }
@@ -4281,7 +4293,7 @@ void flush_pending_by_state(struct state *st)
 {
        struct host_pair *hp = st->st_connection->host_pair;
 
-       if (hp != NULL)
+       if (hp)
        {
                struct pending **pp
                        , *p;
@@ -4299,7 +4311,7 @@ void flush_pending_by_state(struct state *st)
 /* 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;
@@ -4375,20 +4387,19 @@ connection_t *eclipsed(connection_t *c, struct spd_route **esrp)
 
        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;
index 216ab54759b6b790c0b2dc827424614fb29ba29b..e1d7b2c07d8352a65cb8aa55d519fb393628fe8c 100644 (file)
@@ -1,5 +1,6 @@
 /* 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"
 
@@ -130,7 +130,7 @@ extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
 struct virtual_t;
 
 struct end {
-       struct id id;
+       identification_t *id;
        ip_address
                host_addr,
                host_nexthop,
@@ -231,7 +231,7 @@ struct connection {
 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
@@ -262,9 +262,9 @@ extern connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his);
 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) */
 
@@ -274,7 +274,7 @@ extern connection_t* find_host_connection(const ip_address *me,
                                                                                  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,
@@ -298,30 +298,27 @@ extern void get_peer_ca_and_groups(connection_t *c,
  */
 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.
@@ -329,12 +326,9 @@ extern void fmt_conn_instance(const connection_t *c
 
 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);
index 5b2ce4c61fb516be15b5224c611e87af0a0f9d1a..ec56b8530d9a9285f31f229dc3e31d56cdfbc02f 100644 (file)
@@ -36,7 +36,7 @@
 #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"
@@ -238,62 +238,30 @@ stop_adns(void)
 #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;
@@ -349,10 +317,13 @@ process_txt_rr_body(u_char *str
        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)
        {
@@ -360,19 +331,14 @@ process_txt_rr_body(u_char *str
                 * 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 */
                }
        }
@@ -381,23 +347,15 @@ process_txt_rr_body(u_char *str
                /* 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 */
                }
        }
@@ -407,7 +365,7 @@ process_txt_rr_body(u_char *str
                /* 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 */
 
@@ -462,32 +420,26 @@ process_txt_rr_body(u_char *str
 
                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;
@@ -1271,75 +1223,62 @@ process_dns_answer(struct adns_continuation *const cr
 
 /****************************************************************/
 
-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)
        {
@@ -1348,8 +1287,7 @@ gw_addref(struct gw_info *gw)
        }
 }
 
-void
-gw_delref(struct gw_info **gwp)
+void gw_delref(struct gw_info **gwp)
 {
        struct gw_info *gw = *gwp;
 
@@ -1361,10 +1299,12 @@ gw_delref(struct gw_info **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 */
                }
@@ -1414,68 +1354,61 @@ static int adns_in_flight = 0;  /* queries outstanding */
 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().
         */
@@ -1483,7 +1416,6 @@ start_adns_query(const struct id *id    /* domain to query */
        cr->previous = continuations;
        if (continuations != NULL)
        {
-               passert(continuations->next == NULL);
                continuations->next = cr;
        }
        continuations = cr;
@@ -1491,11 +1423,11 @@ start_adns_query(const struct id *id    /* domain to query */
        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;
@@ -1507,15 +1439,12 @@ start_adns_query(const struct id *id    /* domain to query */
        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;
@@ -1620,8 +1549,7 @@ send_unsent_ADNS_queries(void)
  * 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;
@@ -1813,8 +1741,7 @@ process_lwdnsq_answer(char *ts)
 }
 #endif /* USE_LWRES */
 
-static void
-recover_adns_die(void)
+static void recover_adns_die(void)
 {
        struct adns_continuation *cr = NULL;
 
@@ -1848,8 +1775,7 @@ void reset_adns_restart_count(void)
        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 */
index 976c715bfbab602adf01f9eeefbd8c02e4509368..d26a0e64f5c03e183ce637d2f5286a34f0b53bc8 100644 (file)
  * 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);
@@ -33,13 +34,13 @@ struct adns_continuation;       /* forward declaration (not far!) */
 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 */
@@ -47,7 +48,7 @@ struct adns_continuation {
        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;
@@ -56,8 +57,8 @@ struct adns_continuation {
 #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);
@@ -65,18 +66,17 @@ extern err_t start_adns_query(const struct id *id       /* domain to query */
 
 /* 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);
 
index d2a6c0d76ffc3a6893f0108e495ee378cadea5f4..667951ba0232fc7383495cf136136a723b9b22c2 100644 (file)
@@ -33,7 +33,6 @@
 #include "constants.h"
 #include "defs.h"
 #include "log.h"
-#include "id.h"
 #include "x509.h"
 #include "ca.h"
 #include "whack.h"
diff --git a/src/pluto/id.c b/src/pluto/id.c
deleted file mode 100644 (file)
index cd5b350..0000000
+++ /dev/null
@@ -1,537 +0,0 @@
-/* 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:
- */
diff --git a/src/pluto/id.h b/src/pluto/id.h
deleted file mode 100644 (file)
index 8fe1a1f..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-/* 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 */
index 9d5b1cfc9da34a66ebb99910d713058106d033ef..45538b13f87f1cf4043b5b72ed28b2b5520d393f 100644 (file)
 #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"
@@ -1569,7 +1571,7 @@ static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
        }
 }
 
-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
@@ -1593,7 +1595,8 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
                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;
@@ -1611,11 +1614,8 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
                {
                        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);
 
@@ -1678,31 +1678,27 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
 
        /* 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;
@@ -2198,16 +2194,17 @@ static void decode_cert(struct msg_digest *md)
                }
                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
                {
@@ -2276,12 +2273,13 @@ static void decode_cr(struct msg_digest *md, connection_t *c)
  * 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
@@ -2310,74 +2308,50 @@ static bool decode_peer_id(struct msg_digest *md, struct id *peer)
                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);
@@ -2390,7 +2364,7 @@ static bool decode_peer_id(struct msg_digest *md, struct id *peer)
  * - 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;
@@ -2415,16 +2389,11 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
        {
                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;
                }
 
@@ -2467,10 +2436,7 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
 
                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;
                }
 
@@ -2509,10 +2475,9 @@ static bool switch_connection(struct msg_digest *md, struct id *peer,
                }
                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;
@@ -2736,10 +2701,9 @@ static bool has_preloaded_public_key(struct state *st)
                {
                        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 */
@@ -2937,6 +2901,38 @@ static bool uses_pubkey_auth(int auth)
        }
 }
 
+/* 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
@@ -3066,7 +3062,7 @@ stf_status main_inI1_outR1(struct msg_digest *md)
                /* 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 */
@@ -3727,13 +3723,10 @@ struct key_continuation {
 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);
 }
 
 
@@ -3753,12 +3746,14 @@ main_id_and_auth(struct msg_digest *md
 {
        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
@@ -3796,12 +3791,12 @@ main_id_and_auth(struct msg_digest *md
        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)
@@ -3826,22 +3821,14 @@ main_id_and_auth(struct msg_digest *md
 #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 */
 
@@ -3851,7 +3838,7 @@ main_id_and_auth(struct msg_digest *md
 
                        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;
                        }
@@ -3861,7 +3848,7 @@ main_id_and_auth(struct msg_digest *md
        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,
@@ -3874,6 +3861,7 @@ main_id_and_auth(struct msg_digest *md
        }
        if (r != STF_OK)
        {
+               peer->destroy(peer);
                return r;
        }
        DBG(DBG_CRYPT, DBG_log("authentication succeeded"));
@@ -3881,10 +3869,11 @@ main_id_and_auth(struct msg_digest *md
        /*
         * 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;
 }
 
@@ -3928,7 +3917,7 @@ static void key_continue(struct adns_continuation *cr, err_t ugh,
 
                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
@@ -4468,9 +4457,9 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
        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;
 
@@ -4506,20 +4495,20 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
         * %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
@@ -4548,10 +4537,10 @@ static stf_status quick_inI1_outR1_start_query(struct verify_oppo_bundle *b,
 
        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);
@@ -4869,7 +4858,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
                                         * 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
@@ -4878,7 +4867,7 @@ static stf_status quick_inI1_outR1_tail(struct verify_oppo_bundle *b,
                                         * 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
index 2e242e9032311875ad94ee9f15a5ba6b2cc436db..bd717bc2b62301ba4f6601d39988193f6dd79681 100644 (file)
  * 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
@@ -99,4 +104,5 @@ extern void dpd_timeout(struct state *st);
                } \
        }
 
+#endif /* _IPSEC_DOI_H */
 
index 27f25bc8359b384b24137b0adf604ab39af88ca5..97e8a2eea1a3780fab5a32eff0c3263a40727c67 100644 (file)
@@ -45,7 +45,6 @@
 
 #include "constants.h"
 #include "defs.h"
-#include "id.h"
 #include "connections.h"
 #include "state.h"
 #include "timer.h"
@@ -357,6 +356,33 @@ ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
        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
@@ -471,7 +497,7 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                }
 
                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);
@@ -480,7 +506,7 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                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);
@@ -492,12 +518,10 @@ static bool do_command(connection_t *c, struct spd_route *sr,
                {
                        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)
index 828e45d2e1cd6c6e6cd52933f19245d050eea854..f054a6bd99935ff2bc0c2eb76b9e3d5cb7caa41b 100644 (file)
@@ -39,7 +39,6 @@
 
 #include "constants.h"
 #include "defs.h"
-#include "id.h"
 #include "x509.h"
 #include "pgpcert.h"
 #include "certs.h"
@@ -61,7 +60,7 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE;
 typedef struct id_list id_list_t;
 
 struct id_list {
-       struct id id;
+       identification_t *id;
        id_list_t *next;
 };
 
@@ -109,9 +108,7 @@ static const secret_t* get_secret(const connection_t *c,
        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)
@@ -131,23 +128,24 @@ static const secret_t* get_secret(const connection_t *c,
                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)
@@ -170,11 +168,11 @@ static const secret_t* get_secret(const connection_t *c,
 
                                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;
                                        }
@@ -240,6 +238,7 @@ static const secret_t* get_secret(const connection_t *c,
                        }
                }
        }
+       his_id->destroy(his_id);
        return best;
 }
 
@@ -761,16 +760,12 @@ static void log_psk(secret_t *s)
        {
                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);
@@ -947,42 +942,12 @@ static void process_secret_records(int whackfd)
                                        /* 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 */
@@ -1070,11 +1035,11 @@ void free_preshared_secrets(void)
                {
                        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)
index 2b813a87fc9c3ce423e1d787d3188d4524ab0e1d..2f3536ff338c60d0f4ccfb274aebcbd59aaac880 100644 (file)
@@ -38,6 +38,7 @@
 #include "server.h"
 #include "state.h"
 #include "connections.h"
+#include "myid.h"
 #include "kernel.h"
 #include "whack.h"      /* needs connections.h */
 #include "timer.h"
index 1000aa251b106b980289443eaa744e7904dec262..66c46c17ceff6bf677e888399ab3639798754be3 100644 (file)
@@ -1154,7 +1154,8 @@ xauth_inR1(struct msg_digest *md)
 
                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'"
diff --git a/src/pluto/myid.c b/src/pluto/myid.c
new file mode 100644 (file)
index 0000000..f793e01
--- /dev/null
@@ -0,0 +1,121 @@
+/* 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:
+ */
diff --git a/src/pluto/myid.h b/src/pluto/myid.h
new file mode 100644 (file)
index 0000000..012a349
--- /dev/null
@@ -0,0 +1,38 @@
+/* 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 */
index 49d31390e896743b41b40a89feef6f420c706966..3e9831ef80e5f025e37f12e7ed8e274b72985de1 100644 (file)
 #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;
 
 /**
@@ -399,10 +397,11 @@ void share_pgpcert(pgpcert_t *cert)
 /**
  * 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);
 }
 
 /**
index 16169f28953b2a8ad8db567db893c0cb0a1b2fde..27c1605cfe602705079ada28040c5857d6afed33 100644 (file)
@@ -17,6 +17,7 @@
 #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>
@@ -46,7 +47,7 @@ struct pgpcert {
 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);
index 0f392f13587679c3344320f6a9109ee62aa1019c..733dd2623df025bd75c08ca064d2a21f4073caa3 100644 (file)
@@ -19,8 +19,6 @@
 #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 = {
@@ -170,7 +165,8 @@ end:
 /**
  * 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;
@@ -218,24 +214,17 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
                        }
                        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;
@@ -600,22 +589,27 @@ chunk_t pkcs7_build_signedData(chunk_t data, chunk_t attributes,
                                                           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)
index 4122c196b5da6e1aabcfa856321011370205642f..1743ea9c437a9ff0fe523f67292e361e8a090732 100644 (file)
 #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 */
 
@@ -38,7 +37,7 @@ extern const contentInfo_t empty_contentInfo;
 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);
index 203c24c84f03fd79cfcd9e4090b5c5c04de8d129..982f991091da62f2d6e11e7ca64bdfa47490a33b 100644 (file)
@@ -48,7 +48,7 @@
 
 #include "constants.h"
 #include "defs.h"
-#include "id.h"
+#include "myid.h"
 #include "ca.h"
 #include "certs.h"
 #include "ac.h"
@@ -673,7 +673,7 @@ int main(int argc, char **argv)
        init_demux();
        init_kernel();
        init_adns();
-       init_id();
+       init_myid();
        init_fetch();
 
        /* drop unneeded capabilities and change UID/GID */
@@ -762,7 +762,7 @@ void exit_pluto(int status)
        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();
index fbc8e7e2c3b8a89eaef9ae5838f3457708542a79..804c3c43e422678eaa36531647bc0dcbead059fc 100644 (file)
@@ -33,7 +33,6 @@
 
 #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
@@ -102,17 +102,13 @@ struct key_add_continuation {
        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)
        {
@@ -120,9 +116,12 @@ static void key_add_merge(struct key_add_common *oc, const struct id *keyid)
 
                /* 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]);
@@ -155,91 +154,81 @@ static void key_add_continue(struct adns_continuation *ac, err_t ugh)
        }
 
        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
index e6756d8607e57112ccb4cec8027b3cfb0c895f2f..0b28d42da0e741159a0a4124a9d3c951a9f3a4f9 100644 (file)
@@ -24,7 +24,6 @@
 
 #include "constants.h"
 #include "defs.h"
-#include "id.h"
 #include "connections.h"
 #include "state.h"
 #include "packet.h"
@@ -835,19 +834,18 @@ static err_t find_preshared_key(struct state* st)
 
        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;
 }
index a059c52b46e6df38449783e8eb0db95cdbb4c2d0..35ffe5a5b8d8a55bca1fc337178647b91dcf28bb 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <crypto/diffie_hellman.h>
 
+#include "defs.h"
 #include "connections.h"
 
 /* Message ID mechanism.
index 3b9f6d7a082fa4f11f3208eec12b39508361ac64..47c9cecffab7f0d7f8efdc025af634bc0b6d5ecf 100644 (file)
@@ -26,8 +26,6 @@
 #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>
@@ -35,7 +33,6 @@
 #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 */
@@ -76,666 +56,6 @@ const x509cert_t empty_x509cert = {
 
 /* 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
  */
@@ -779,25 +99,22 @@ x509cert_t* add_x509cert(x509cert_t *cert)
 /**
  * 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;
@@ -805,23 +122,17 @@ void select_x509cert_id(x509cert_t *cert, struct id *end_id)
                }
                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;
        }
 }
 
@@ -899,42 +210,40 @@ void release_x509cert(x509cert_t *cert)
 /**
  * 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 */
 
@@ -957,27 +266,33 @@ void store_x509certs(x509cert_t **firstcert, bool strict)
 
        /* 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);
 }
 
 /**
index 8fabcaf5c5832f1cc3cb1fd06bb8710f9951b3eb..40e7e7e5dac32ec6ba98a804a8386e5419ab72d6 100644 (file)
 #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 */
 
@@ -41,12 +41,7 @@ struct x509cert {
 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);
@@ -60,7 +55,7 @@ extern x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cer
 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);
index 36a38a628461b9e6b9848e2f0c4fd9f1b0919d57..3693b75324ee035acc57245039c3e5f409fc76b1 100644 (file)
@@ -24,8 +24,7 @@ LIBSTRONGSWANBUILDDIR=$(top_builddir)/src/libstrongswan
 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
 
@@ -37,44 +36,15 @@ endif
 
 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 $@ $<
index 91f89cc62679aa6ef8c7b2138b3937baf420f071..576ce1dc5ab96d42aef1e8ff603879832d04a686 100644 (file)
@@ -54,8 +54,8 @@
 #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"
 
@@ -789,10 +789,10 @@ int main(int argc, char **argv)
         */
        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 */
        {
@@ -1020,10 +1020,12 @@ int main(int argc, char **argv)
         */
        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;
@@ -1115,7 +1117,7 @@ int main(int argc, char **argv)
                {
                        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");
                }
@@ -1123,11 +1125,12 @@ int main(int argc, char **argv)
 
                /* 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))
                        {
@@ -1135,7 +1138,7 @@ int main(int argc, char **argv)
                                {
                                        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);
@@ -1143,9 +1146,8 @@ int main(int argc, char **argv)
                                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 */
        }
 
index 865e8e59092eebb3476d3a562691fcecb484393c..5a04171c21183cbf4f5e94efb5cd03e66939c705 100644 (file)
@@ -17,6 +17,8 @@
 
 #include <freeswan.h>
 
+#include <defs.h>
+
 /* copy of smartcard operations, defined in smartcard.h */
 #ifndef SC_OP_T
 #define SC_OP_T