From: Andreas Steffen Date: Sat, 10 Oct 2009 19:16:46 +0000 (+0200) Subject: replaced struct id by identification_t X-Git-Tag: 4.3.5rc1~50 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=17722d448931ec01c35ccd37d5dd8bee8e9074f5;p=thirdparty%2Fstrongswan.git replaced struct id by identification_t --- diff --git a/src/pluto/Makefile.am b/src/pluto/Makefile.am index b481a50a9c..e966299c01 100644 --- a/src/pluto/Makefile.am +++ b/src/pluto/Makefile.am @@ -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 \ diff --git a/src/pluto/alg_info.c b/src/pluto/alg_info.c index 1cc2d189e1..a9a6dd5f0a 100644 --- a/src/pluto/alg_info.c +++ b/src/pluto/alg_info.c @@ -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; } /* diff --git a/src/pluto/builder.c b/src/pluto/builder.c index 004145103a..39a85eddb8 100644 --- a/src/pluto/builder.c +++ b/src/pluto/builder.c @@ -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" diff --git a/src/pluto/certs.c b/src/pluto/certs.c index 456a45fca3..89e289b6ca 100644 --- a/src/pluto/certs.c +++ b/src/pluto/certs.c @@ -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); diff --git a/src/pluto/connections.c b/src/pluto/connections.c index 01a80a1006..a1cf2103e6 100644 --- a/src/pluto/connections.c +++ b/src/pluto/connections.c @@ -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]=""; @@ -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; diff --git a/src/pluto/connections.h b/src/pluto/connections.h index 216ab54759..e1d7b2c07d 100644 --- a/src/pluto/connections.h +++ b/src/pluto/connections.h @@ -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 @@ -19,10 +20,9 @@ #include #include +#include -#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); diff --git a/src/pluto/dnskey.c b/src/pluto/dnskey.c index 5b2ce4c61f..ec56b8530d 100644 --- a/src/pluto/dnskey.c +++ b/src/pluto/dnskey.c @@ -36,7 +36,7 @@ #include "adns.h" /* needs */ #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 */ diff --git a/src/pluto/dnskey.h b/src/pluto/dnskey.h index 976c715bfb..d26a0e64f5 100644 --- a/src/pluto/dnskey.h +++ b/src/pluto/dnskey.h @@ -12,9 +12,10 @@ * for more details. */ -extern int - adns_qfd, /* file descriptor for sending queries to adns */ - adns_afd; /* file descriptor for receiving answers from adns */ +#include + +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); diff --git a/src/pluto/fetch.c b/src/pluto/fetch.c index d2a6c0d76f..667951ba02 100644 --- a/src/pluto/fetch.c +++ b/src/pluto/fetch.c @@ -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 index cd5b350752..0000000000 --- a/src/pluto/id.c +++ /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 . - * - * 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 -#include -#include -#include -#include -#include -#include -#include -#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says defines this */ -# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ -#endif -#include - -#include - -#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 index 8fe1a1f46a..0000000000 --- a/src/pluto/id.h +++ /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 . - * - * 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 - -#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 */ diff --git a/src/pluto/ipsec_doi.c b/src/pluto/ipsec_doi.c index 9d5b1cfc9d..45538b13f8 100644 --- a/src/pluto/ipsec_doi.c +++ b/src/pluto/ipsec_doi.c @@ -35,12 +35,14 @@ #include #include #include +#include #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 diff --git a/src/pluto/ipsec_doi.h b/src/pluto/ipsec_doi.h index 2e242e9032..bd717bc2b6 100644 --- a/src/pluto/ipsec_doi.h +++ b/src/pluto/ipsec_doi.h @@ -12,6 +12,11 @@ * 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 */ diff --git a/src/pluto/kernel.c b/src/pluto/kernel.c index 27f25bc835..97e8a2eea1 100644 --- a/src/pluto/kernel.c +++ b/src/pluto/kernel.c @@ -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) diff --git a/src/pluto/keys.c b/src/pluto/keys.c index 828e45d2e1..f054a6bd99 100644 --- a/src/pluto/keys.c +++ b/src/pluto/keys.c @@ -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) diff --git a/src/pluto/log.c b/src/pluto/log.c index 2b813a87fc..2f3536ff33 100644 --- a/src/pluto/log.c +++ b/src/pluto/log.c @@ -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" diff --git a/src/pluto/modecfg.c b/src/pluto/modecfg.c index 1000aa251b..66c46c17ce 100644 --- a/src/pluto/modecfg.c +++ b/src/pluto/modecfg.c @@ -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 index 0000000000..f793e011ca --- /dev/null +++ b/src/pluto/myid.c @@ -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 . + * + * 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 +#include + +#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says defines this */ +# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */ +#endif + +#include + +#include + +#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 index 0000000000..012a34968e --- /dev/null +++ b/src/pluto/myid.h @@ -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 . + * + * 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 + +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 */ diff --git a/src/pluto/pgpcert.c b/src/pluto/pgpcert.c index 49d31390e8..3e9831ef80 100644 --- a/src/pluto/pgpcert.c +++ b/src/pluto/pgpcert.c @@ -27,13 +27,11 @@ #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); } /** diff --git a/src/pluto/pgpcert.h b/src/pluto/pgpcert.h index 16169f2895..27c1605cfe 100644 --- a/src/pluto/pgpcert.h +++ b/src/pluto/pgpcert.h @@ -17,6 +17,7 @@ #ifndef _PGPCERT_H #define _PGPCERT_H +#include #include #include #include @@ -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); diff --git a/src/pluto/pkcs7.c b/src/pluto/pkcs7.c index 0f392f1358..733dd2623d 100644 --- a/src/pluto/pkcs7.c +++ b/src/pluto/pkcs7.c @@ -19,8 +19,6 @@ #include #include -#include - #include #include #include @@ -28,11 +26,8 @@ #include #include #include +#include -#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) diff --git a/src/pluto/pkcs7.h b/src/pluto/pkcs7.h index 4122c196b5..1743ea9c43 100644 --- a/src/pluto/pkcs7.h +++ b/src/pluto/pkcs7.h @@ -18,11 +18,10 @@ #ifndef _PKCS7_H #define _PKCS7_H +#include #include #include #include -#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); diff --git a/src/pluto/plutomain.c b/src/pluto/plutomain.c index 203c24c84f..982f991091 100644 --- a/src/pluto/plutomain.c +++ b/src/pluto/plutomain.c @@ -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(); diff --git a/src/pluto/rcv_whack.c b/src/pluto/rcv_whack.c index fbc8e7e2c3..804c3c43e4 100644 --- a/src/pluto/rcv_whack.c +++ b/src/pluto/rcv_whack.c @@ -33,7 +33,6 @@ #include "constants.h" #include "defs.h" -#include "id.h" #include "ca.h" #include "certs.h" #include "ac.h" @@ -55,9 +54,10 @@ #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 diff --git a/src/pluto/spdb.c b/src/pluto/spdb.c index e6756d8607..0b28d42da0 100644 --- a/src/pluto/spdb.c +++ b/src/pluto/spdb.c @@ -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; } diff --git a/src/pluto/state.h b/src/pluto/state.h index a059c52b46..35ffe5a5b8 100644 --- a/src/pluto/state.h +++ b/src/pluto/state.h @@ -21,6 +21,7 @@ #include +#include "defs.h" #include "connections.h" /* Message ID mechanism. diff --git a/src/pluto/x509.c b/src/pluto/x509.c index 3b9f6d7a08..47c9cecffa 100644 --- a/src/pluto/x509.c +++ b/src/pluto/x509.c @@ -26,8 +26,6 @@ #include #include -#include -#include #include #include #include @@ -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" @@ -50,23 +47,6 @@ */ 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); } /** diff --git a/src/pluto/x509.h b/src/pluto/x509.h index 8fabcaf5c5..40e7e7e5da 100644 --- a/src/pluto/x509.h +++ b/src/pluto/x509.h @@ -19,12 +19,12 @@ #define _X509_H #include +#include #include #include #include #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); diff --git a/src/scepclient/Makefile.am b/src/scepclient/Makefile.am index 36a38a6284..3693b75324 100644 --- a/src/scepclient/Makefile.am +++ b/src/scepclient/Makefile.am @@ -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 $@ $< diff --git a/src/scepclient/scepclient.c b/src/scepclient/scepclient.c index 91f89cc626..576ce1dc5a 100644 --- a/src/scepclient/scepclient.c +++ b/src/scepclient/scepclient.c @@ -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 */ } diff --git a/src/whack/whack.h b/src/whack/whack.h index 865e8e5909..5a04171c21 100644 --- a/src/whack/whack.h +++ b/src/whack/whack.h @@ -17,6 +17,8 @@ #include +#include + /* copy of smartcard operations, defined in smartcard.h */ #ifndef SC_OP_T #define SC_OP_T