replaced struct id by identification_t

This commit is contained in:
Andreas Steffen
2009-10-10 21:19:38 +02:00
parent 55b045abb5
commit 17722d4489
32 changed files with 988 additions and 2249 deletions
+1 -1
View File
@@ -20,7 +20,6 @@ demux.c demux.h \
dnskey.c dnskey.h \
fetch.c fetch.h \
foodgroups.c foodgroups.h \
id.c id.h \
ike_alg.c ike_alg.h \
ipsec_doi.c ipsec_doi.h \
kameipsec.h \
@@ -32,6 +31,7 @@ kernel_pfkey.c kernel_pfkey.h \
keys.c keys.h \
lex.c lex.h \
log.c log.h \
myid.c myid.h \
modecfg.c modecfg.h \
nat_traversal.c nat_traversal.h \
ocsp.c ocsp.h \
+13 -5
View File
@@ -461,12 +461,16 @@ struct alg_info_esp *alg_info_esp_create_from_str(char *alg_str)
status = alg_info_parse_str((struct alg_info *)alg_info_esp, alg_str);
out:
if (status != SUCCESS)
if (status == SUCCESS)
{
alg_info_esp->ref_cnt = 1;
return alg_info_esp;
}
else
{
free(alg_info_esp);
alg_info_esp = NULL;
return NULL;
}
return alg_info_esp;
}
struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
@@ -481,12 +485,16 @@ struct alg_info_ike *alg_info_ike_create_from_str(char *alg_str)
zero(alg_info_ike);
alg_info_ike->alg_info_protoid = PROTO_ISAKMP;
if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) != SUCCESS)
if (alg_info_parse_str((struct alg_info *)alg_info_ike, alg_str) == SUCCESS)
{
alg_info_ike->ref_cnt = 1;
return alg_info_ike;
}
else
{
free(alg_info_ike);
return NULL;
}
return alg_info_ike;
}
/*
-1
View File
@@ -30,7 +30,6 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
#include "certs.h"
#include "ac.h"
#include "crl.h"
+4 -7
View File
@@ -28,7 +28,6 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
#include "certs.h"
#include "whack.h"
#include "builder.h"
@@ -228,10 +227,9 @@ void share_cert(cert_t cert)
}
/* release of a certificate decreases the count by one
" the certificate is freed when the counter reaches zero
* the certificate is freed when the counter reaches zero
*/
void
release_cert(cert_t cert)
void release_cert(cert_t cert)
{
switch (cert.type)
{
@@ -246,11 +244,10 @@ release_cert(cert_t cert)
}
}
/*
/**
* list all X.509 and OpenPGP end certificates
*/
void
list_certs(bool utc)
void list_certs(bool utc)
{
list_x509_end_certs(utc);
list_pgp_end_certs(utc);
+295 -284
View File
File diff suppressed because it is too large Load Diff
+27 -33
View File
@@ -1,5 +1,6 @@
/* information about connections between hosts and clients
* Copyright (C) 1998-2001 D. Hugh Redelmeier
* Copyright (C) 2009 Andreas Steffen - Hochschule fuer Technik Rapperswil
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -19,10 +20,9 @@
#include <utils/linked_list.h>
#include <utils/identification.h>
#include <credentials/ietf_attributes/ietf_attributes.h>
#include "id.h"
#include "certs.h"
#include "ac.h"
#include "smartcard.h"
#include "whack.h"
@@ -130,7 +130,7 @@ extern void fmt_policy_prio(policy_prio_t pp, char buf[POLICY_PRIO_BUF]);
struct virtual_t;
struct end {
struct id id;
identification_t *id;
ip_address
host_addr,
host_nexthop,
@@ -231,7 +231,7 @@ struct connection {
extern bool orient(connection_t *c);
extern bool same_peer_ids(const connection_t *c, const connection_t *d,
const struct id *his_id);
identification_t *his_id);
/* Format the topology of a connection end, leaving out defaults.
* Largest left end looks like: client === host : port [ host_id ] --- hop
@@ -262,9 +262,9 @@ extern connection_t *shunt_owner(const ip_subnet *ours, const ip_subnet *his);
extern bool uniqueIDs; /* --uniqueids? */
extern void ISAKMP_SA_established(connection_t *c, so_serial_t serial);
#define his_id_was_instantiated(c) ((c)->kind == CK_INSTANCE \
&& (id_is_ipaddr(&(c)->spd.that.id)? \
sameaddr(&(c)->spd.that.id.ip_addr, &(c)->spd.that.host_addr) : TRUE))
#define id_is_ipaddr(id) ((id)->get_type(id) == ID_IPV4_ADDR || \
(id)->get_type(id) == ID_IPV6_ADDR)
extern bool his_id_was_instantiated(const connection_t *c);
struct state; /* forward declaration of tag (defined in state.h) */
@@ -274,7 +274,7 @@ extern connection_t* find_host_connection(const ip_address *me,
const ip_address *him,
u_int16_t his_port, lset_t policy);
extern connection_t* refine_host_connection(const struct state *st,
const struct id *id,
identification_t *id,
identification_t *peer_ca);
extern connection_t* find_client_connection(connection_t *c,
const ip_subnet *our_net,
@@ -298,30 +298,27 @@ extern void get_peer_ca_and_groups(connection_t *c,
*/
struct gw_info; /* forward declaration of tag (defined in dnskey.h) */
struct alg_info; /* forward declaration of tag (defined in alg_info.h) */
extern connection_t *rw_instantiate(connection_t *c
, const ip_address *him
, u_int16_t his_port
, const ip_subnet *his_net
, const struct id *his_id);
extern connection_t *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
, const struct id *his_id
, struct gw_info *gw
, const ip_address *our_client
, const ip_address *peer_client);
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);
+103 -177
View File
@@ -36,7 +36,7 @@
#include "adns.h" /* needs <resolv.h> */
#include "defs.h"
#include "log.h"
#include "id.h"
#include "myid.h"
#include "connections.h"
#include "keys.h" /* needs connections.h */
#include "dnskey.h"
@@ -238,62 +238,30 @@ stop_adns(void)
#define our_TXT_attr_string "X-IPsec-Server"
static const char our_TXT_attr[] = our_TXT_attr_string;
static err_t
decode_iii(u_char **pp, struct id *gw_id)
identification_t* decode_iii(u_char **pp)
{
identification_t *gw_id;
u_char *p = *pp + strspn(*pp, " \t");
u_char *e = p + strcspn(p, " \t");
u_char under = *e;
if (p == e)
{
return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
return NULL;
}
*e = '\0';
if (*p == '@')
{
/* gateway specification in this record is @FQDN */
err_t ugh = atoid(p, gw_id, FALSE);
if (ugh != NULL)
{
return builddiag("malformed FQDN in TXT " our_TXT_attr_string ": %s"
, ugh);
}
}
else
{
/* gateway specification is numeric */
ip_address ip;
err_t ugh = tnatoaddr(p, e-p
, strchr(p, ':') == NULL? AF_INET : AF_INET6
, &ip);
if (ugh != NULL)
{
return builddiag("malformed IP address in TXT " our_TXT_attr_string ": %s"
, ugh);
}
if (isanyaddr(&ip))
{
return "gateway address must not be 0.0.0.0 or 0::0";
}
iptoid(&ip, gw_id);
}
gw_id = identification_create_from_string(p);
*e = under;
*pp = e + strspn(e, " \t");
return NULL;
return gw_id;
}
static err_t
process_txt_rr_body(u_char *str
, bool doit /* should we capture information? */
, enum dns_auth_level dns_auth_level
, struct adns_continuation *const cr)
static err_t process_txt_rr_body(u_char *str, bool doit,
enum dns_auth_level dns_auth_level,
struct adns_continuation *const cr)
{
const struct id *client_id = &cr->id; /* subject of query */
identification_t *client_id = cr->id; /* subject of query */
u_char *p = str;
unsigned long pref = 0;
struct gw_info gi;
@@ -349,10 +317,13 @@ process_txt_rr_body(u_char *str
p += strspn(p, " \t");
/* Decode iii (Security Gateway ID). */
zero(&gi); /* before first use */
TRY(decode_iii(&p, &gi.gw_id)); /* will need to unshare_id_content */
gi.gw_id = decode_iii(&p);
if (gi.gw_id == NULL)
{
return "TXT " our_TXT_attr_string " badly formed (no gateway specified)";
}
if (!cr->sgw_specified)
{
@@ -360,19 +331,14 @@ process_txt_rr_body(u_char *str
* and we don't know who to initiate with.
* So we're looking for gateway specs with an IP address
*/
if (!id_is_ipaddr(&gi.gw_id))
if (gi.gw_id->get_type(gi.gw_id) != ID_IPV4_ADDR &&
gi.gw_id->get_type(gi.gw_id) != ID_IPV6_ADDR)
{
DBG(DBG_DNS,
{
char cidb[BUF_LEN];
char gwidb[BUF_LEN];
idtoa(client_id, cidb, sizeof(cidb));
idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
DBG_log("TXT %s record for %s: security gateway %s;"
" ignored because gateway's IP is unspecified"
, our_TXT_attr, cidb, gwidb);
});
DBG_log("TXT %s record for '%Y': security gateway '%Y';"
" ignored because gateway's IP is unspecified",
our_TXT_attr, client_id, gi.gw_id);
)
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
@@ -381,23 +347,15 @@ process_txt_rr_body(u_char *str
/* We do know the peer's ID (because we are responding)
* So we're looking for gateway specs specifying this known ID.
*/
const struct id *peer_id = &cr->sgw_id;
identification_t *peer_id = cr->sgw_id;
if (!same_id(peer_id, &gi.gw_id))
if (!peer_id->equals(peer_id, gi.gw_id))
{
DBG(DBG_DNS,
{
char cidb[BUF_LEN];
char gwidb[BUF_LEN];
char pidb[BUF_LEN];
idtoa(client_id, cidb, sizeof(cidb));
idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
idtoa(peer_id, pidb, sizeof(pidb));
DBG_log("TXT %s record for %s: security gateway %s;"
" ignored -- looking to confirm %s as gateway"
, our_TXT_attr, cidb, gwidb, pidb);
});
DBG_log("TXT %s record for '%Y': security gateway '%Y';"
" ignored -- looking to confirm '%Y' as gateway",
our_TXT_attr, client_id, gi.gw_id, peer_id);
)
return NULL; /* we cannot use this record, but it isn't wrong */
}
}
@@ -407,7 +365,7 @@ process_txt_rr_body(u_char *str
/* really accept gateway */
struct gw_info **gwip; /* gateway insertion point */
gi.client_id = *client_id; /* will need to unshare_id_content */
gi.client_id = client_id; /* will need to unshare_id_content */
/* decode optional kkk: base 64 encoding of key */
@@ -462,32 +420,26 @@ process_txt_rr_body(u_char *str
DBG(DBG_DNS,
{
char cidb[BUF_LEN];
char gwidb[BUF_LEN];
chunk_t keyid;
public_key_t *key;
idtoa(client_id, cidb, sizeof(cidb));
idtoa(&gi.gw_id, gwidb, sizeof(gwidb));
key = gi.key->public_key;
public_key_t *key = gi.key->public_key;
if (gi.gw_key_present &&
key->get_fingerprint(key, KEY_ID_PUBKEY_SHA1, &keyid))
{
DBG_log("gateway for %s is %s with key %#B"
, cidb, gwidb, &keyid);
DBG_log("gateway for %s is %s with key %#B",
client_id, gi.gw_id, &keyid);
}
else
{
DBG_log("gateway for %s is %s; no key specified"
, cidb, gwidb);
DBG_log("gateway for '%Y' is '%Y'; no key specified",
client_id, gi.gw_id);
}
});
gi.next = *gwip;
*gwip = clone_thing(gi);
unshare_id_content(&(*gwip)->gw_id);
unshare_id_content(&(*gwip)->client_id);
(*gwip)->gw_id = (*gwip)->gw_id->clone((*gwip)->gw_id);
(*gwip)->client_id = (*gwip)->client_id->clone((*gwip)->client_id);
}
return NULL;
@@ -1271,75 +1223,62 @@ process_dns_answer(struct adns_continuation *const cr
/****************************************************************/
static err_t
build_dns_name(u_char name_buf[NS_MAXDNAME + 2]
, unsigned long serial USED_BY_DEBUG
, const struct id *id
, const char *typename USED_BY_DEBUG
, const char *gwname USED_BY_DEBUG)
static err_t build_dns_name(u_char name_buf[NS_MAXDNAME + 2],
unsigned long serial USED_BY_DEBUG,
identification_t *id,
const char *typename USED_BY_DEBUG,
identification_t *gw USED_BY_DEBUG)
{
/* note: all end in "." to suppress relative searches */
id = resolve_myid(id);
switch (id->kind)
{
case ID_IPV4_ADDR:
{
/* XXX: this is really ugly and only temporary until addrtot can
* generate the correct format
*/
const unsigned char *b;
size_t bl USED_BY_DEBUG = addrbytesptr(&id->ip_addr, &b);
passert(bl == 4);
snprintf(name_buf, NS_MAXDNAME + 2, "%d.%d.%d.%d.in-addr.arpa."
, b[3], b[2], b[1], b[0]);
break;
}
case ID_IPV6_ADDR:
switch (id->get_type(id))
{
/* ??? is this correct? */
const unsigned char *b;
size_t bl;
u_char *op = name_buf;
static const char suffix[] = "IP6.INT.";
for (bl = addrbytesptr(&id->ip_addr, &b); bl-- != 0; )
case ID_IPV4_ADDR:
{
if (op + 4 + sizeof(suffix) >= name_buf + NS_MAXDNAME + 1)
return "IPv6 reverse name too long";
op += sprintf(op, "%x.%x.", b[bl] & 0xF, b[bl] >> 4);
chunk_t b = id->get_encoding(id);
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;
}
strcpy(op, suffix);
break;
}
case ID_FQDN:
/* strip trailing "." characters, then add one */
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 */
+20 -20
View File
@@ -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 <utils/identification.h>
extern int adns_qfd; /* file descriptor for sending queries to adns */
extern int adns_afd; /* file descriptor for receiving answers from adns */
extern const char *pluto_adns_option; /* path from --pluto_adns */
extern void init_adns(void);
extern void stop_adns(void);
@@ -33,13 +34,13 @@ struct adns_continuation; /* forward declaration (not far!) */
typedef void (*cont_fn_t)(struct adns_continuation *cr, err_t ugh);
struct adns_continuation {
unsigned long qtid; /* query transaction id number */
int type; /* T_TXT or T_KEY, selecting rr type of interest */
cont_fn_t cont_fn; /* function to carry on suspended work */
struct id id; /* subject of query */
unsigned long qtid; /* query transaction id number */
int type; /* T_TXT or T_KEY, selecting rr type of interest */
cont_fn_t cont_fn; /* function to carry on suspended work */
identification_t *id; /* subject of query */
bool sgw_specified;
struct id sgw_id; /* peer, if constrained */
lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
identification_t *sgw_id; /* peer, if constrained */
lset_t debugging; /* only used #ifdef DEBUG, but don't want layout to change */
struct gw_info *gateways_from_dns; /* answer, if looking for our TXT rrs */
#ifdef USE_KEYRR
struct pubkey_list *keys_from_dns; /* answer, if looking for KEY rrs */
@@ -47,7 +48,7 @@ struct adns_continuation {
struct adns_continuation *previous, *next;
struct pubkey *last_info; /* the last structure we accumulated */
#ifdef USE_LWRES
bool used; /* have we called the cont_fn yet? */
bool used; /* have we called the cont_fn yet? */
struct {
u_char name_buf[NS_MAXDNAME + 2];
} query;
@@ -56,8 +57,8 @@ struct adns_continuation {
#endif /* ! USE_LWRES */
};
extern err_t start_adns_query(const struct id *id /* domain to query */
, const struct id *sgw_id /* if non-null, any accepted gw_info must match */
extern err_t start_adns_query(identification_t *id /* domain to query */
, identification_t *sgw_id /* if non-null, any accepted gw_info must match */
, int type /* T_TXT or T_KEY, selecting rr type of interest */
, cont_fn_t cont_fn /* continuation function */
, struct adns_continuation *cr);
@@ -65,18 +66,17 @@ extern err_t start_adns_query(const struct id *id /* domain to query */
/* Gateway info gleaned from reverse DNS of client */
struct gw_info {
unsigned refcnt; /* reference counted! */
unsigned pref; /* preference: lower is better */
#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
struct id client_id; /* id of client of peer */
struct id gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
unsigned refcnt; /* reference counted! */
unsigned pref; /* preference: lower is better */
#define NO_TIME ((time_t) -2) /* time_t value meaning "not_yet" */
identification_t* client_id; /* id of client of peer */
identification_t* gw_id; /* id of peer (if id_is_ipaddr, .ip_addr is address) */
bool gw_key_present;
struct pubkey *key;
struct gw_info *next;
};
extern void gw_addref(struct gw_info *gw)
, gw_delref(struct gw_info **gwp);
extern void gw_addref(struct gw_info *gw);
extern void gw_delref(struct gw_info **gwp);
extern void reset_adns_restart_count(void);
-1
View File
@@ -33,7 +33,6 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
#include "x509.h"
#include "ca.h"
#include "whack.h"
-537
View File
@@ -1,537 +0,0 @@
/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
* Copyright (C) 1999-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
#endif
#include <sys/queue.h>
#include <freeswan.h>
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "log.h"
#include "connections.h"
#include "packet.h"
#include "whack.h"
const struct id empty_id; /* ID_ANY */
enum myid_state myid_state = MYID_UNKNOWN;
struct id myids[MYID_SPECIFIED+1]; /* %myid */
char *myid_str[MYID_SPECIFIED+1]; /* string form of IDs */
/* initialize id module
* Fills in myid from environment variable IPSECmyid or defaultrouteaddr
*/
void init_id(void)
{
passert(empty_id.kind == ID_ANY);
myid_state = MYID_UNKNOWN;
{
enum myid_state s;
for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
{
myids[s] = empty_id;
myid_str[s] = NULL;
}
}
set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
set_myid(MYID_IP, getenv("defaultrouteaddr"));
set_myFQDN();
}
/*
* free id module
*/
void free_id(void)
{
enum myid_state s;
for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
{
free_id_content(&myids[s]);
free(myid_str[s]);
}
}
static void calc_myid_str(enum myid_state s)
{
/* preformat the ID name */
char buf[BUF_LEN];
idtoa(&myids[s], buf, BUF_LEN);
replace(myid_str[s], clone_str(buf));
}
void set_myid(enum myid_state s, char *idstr)
{
if (idstr != NULL)
{
struct id id;
err_t ugh = atoid(idstr, &id, FALSE);
if (ugh != NULL)
{
loglog(RC_BADID, "myid malformed: %s \"%s\"", ugh, idstr);
}
else
{
free_id_content(&myids[s]);
unshare_id_content(&id);
myids[s] = id;
if (s == MYID_SPECIFIED)
myid_state = MYID_SPECIFIED;
calc_myid_str(s);
}
}
}
void set_myFQDN(void)
{
char FQDN[HOST_NAME_MAX + 1];
int r = gethostname(FQDN, sizeof(FQDN));
free_id_content(&myids[MYID_HOSTNAME]);
myids[MYID_HOSTNAME] = empty_id;
if (r != 0)
{
log_errno((e, "gethostname() failed in set_myFQDN"));
}
else
{
FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
{
size_t len = strlen(FQDN);
if (len > 0 && FQDN[len-1] == '.')
{
/* nuke trailing . */
FQDN[len-1]='\0';
}
}
if (!strcaseeq(FQDN, "localhost.localdomain"))
{
chunk_t myid_name = { FQDN, strlen(FQDN) };
myids[MYID_HOSTNAME].name = chunk_clone(myid_name);
myids[MYID_HOSTNAME].kind = ID_FQDN;
calc_myid_str(MYID_HOSTNAME);
}
}
}
void show_myid_status(void)
{
char idstr[BUF_LEN];
(void)idtoa(&myids[myid_state], idstr, sizeof(idstr));
whack_log(RC_COMMENT, "%%myid = %s", idstr);
}
/* Convert textual form of id into a (temporary) struct id.
* Note that if the id is to be kept, unshare_id_content will be necessary.
*/
err_t atoid(char *src, struct id *id, bool myid_ok)
{
err_t ugh = NULL;
*id = empty_id;
if (myid_ok && streq("%myid", src))
{
id->kind = ID_MYID;
}
else if (strchr(src, '=') != NULL)
{
/* we interpret this as an ASCII X.501 ID_DER_ASN1_DN */
id->kind = ID_DER_ASN1_DN;
id->name.ptr = temporary_cyclic_buffer(); /* assign temporary buffer */
id->name.len = 0;
/* convert from LDAP style or openssl x509 -subject style to ASN.1 DN
* discard optional @ character in front of DN
*/
ugh = atodn((*src == '@')?src+1:src, &id->name);
}
else if (strchr(src, '@') == NULL)
{
if (streq(src, "%any") || streq(src, "0.0.0.0"))
{
/* any ID will be accepted */
id->kind = ID_ANY;
}
else
{
/* !!! this test is not sufficient for distinguishing address families.
* We need a notation to specify that a FQDN is to be resolved to IPv6.
*/
const struct af_info *afi = strchr(src, ':') == NULL
? &af_inet4_info: &af_inet6_info;
id->kind = afi->id_addr;
ugh = ttoaddr(src, 0, afi->af, &id->ip_addr);
}
}
else
{
if (*src == '@')
{
if (*(src+1) == '#')
{
/* if there is a second specifier (#) on the line
* we interprete this as ID_KEY_ID
*/
id->kind = ID_KEY_ID;
id->name.ptr = src;
/* discard @~, convert from hex to bin */
ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
}
else if (*(src+1) == '~')
{
/* if there is a second specifier (~) on the line
* we interprete this as a binary ID_DER_ASN1_DN
*/
id->kind = ID_DER_ASN1_DN;
id->name.ptr = src;
/* discard @~, convert from hex to bin */
ugh = ttodata(src+2, 0, 16, id->name.ptr, strlen(src), &id->name.len);
}
else
{
id->kind = ID_FQDN;
id->name.ptr = src+1; /* discard @ */
id->name.len = strlen(src)-1;
}
}
else
{
/* We leave in @, as per DOI 4.6.2.4
* (but DNS wants . instead).
*/
id->kind = ID_USER_FQDN;
id->name.ptr = src;
id->name.len = strlen(src);
}
}
return ugh;
}
/*
* Converts a binary key ID into hexadecimal format
*/
int keyidtoa(char *dst, size_t dstlen, chunk_t keyid)
{
int n = datatot(keyid.ptr, keyid.len, 'x', dst, dstlen);
return (((size_t)n < dstlen)? n : dstlen) - 1;
}
void iptoid(const ip_address *ip, struct id *id)
{
*id = empty_id;
switch (addrtypeof(ip))
{
case AF_INET:
id->kind = ID_IPV4_ADDR;
break;
case AF_INET6:
id->kind = ID_IPV6_ADDR;
break;
default:
bad_case(addrtypeof(ip));
}
id->ip_addr = *ip;
}
int idtoa(const struct id *id, char *dst, size_t dstlen)
{
int n;
id = resolve_myid(id);
switch (id->kind)
{
case ID_ANY:
n = snprintf(dst, dstlen, "(none)");
break;
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
n = (int)addrtot(&id->ip_addr, 0, dst, dstlen) - 1;
break;
case ID_FQDN:
n = snprintf(dst, dstlen, "@%.*s", (int)id->name.len, id->name.ptr);
break;
case ID_USER_FQDN:
n = snprintf(dst, dstlen, "%.*s", (int)id->name.len, id->name.ptr);
break;
case ID_DER_ASN1_DN:
n = dntoa(dst, dstlen, id->name);
break;
case ID_KEY_ID:
n = keyidtoa(dst, dstlen, id->name);
break;
default:
n = snprintf(dst, dstlen, "unknown id kind %d", id->kind);
break;
}
/* "Sanitize" string so that log isn't endangered:
* replace unprintable characters with '?'.
*/
if (n > 0)
{
for ( ; *dst != '\0'; dst++)
if (!isprint(*dst))
*dst = '?';
}
return n;
}
/* Replace the shell metacharacters ', \, ", `, and $ in a character string
* by escape sequences consisting of their octal values
*/
void escape_metachar(const char *src, char *dst, size_t dstlen)
{
while (*src != '\0' && dstlen > 4)
{
switch (*src)
{
case '\'':
case '\\':
case '"':
case '`':
case '$':
sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
dst += 4;
dstlen -= 4;
break;
default:
*dst++ = *src;
dstlen--;
}
src++;
}
*dst = '\0';
}
/* Make private copy of string in struct id.
* This is needed if the result of atoid is to be kept.
*/
void unshare_id_content(struct id *id)
{
switch (id->kind)
{
case ID_FQDN:
case ID_USER_FQDN:
case ID_DER_ASN1_DN:
case ID_KEY_ID:
id->name = chunk_clone(id->name);
break;
case ID_MYID:
case ID_ANY:
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
break;
default:
bad_case(id->kind);
}
}
void free_id_content(struct id *id)
{
switch (id->kind)
{
case ID_FQDN:
case ID_USER_FQDN:
case ID_DER_ASN1_DN:
case ID_KEY_ID:
free(id->name.ptr);
break;
case ID_MYID:
case ID_ANY:
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
break;
default:
bad_case(id->kind);
}
}
/* compare two struct id values */
bool same_id(const struct id *a, const struct id *b)
{
a = resolve_myid(a);
b = resolve_myid(b);
if (a->kind != b->kind)
return FALSE;
switch (a->kind)
{
case ID_ANY:
return TRUE; /* kind of vacuous */
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
return sameaddr(&a->ip_addr, &b->ip_addr);
case ID_FQDN:
case ID_USER_FQDN:
/* assumptions:
* - case should be ignored
* - trailing "." should be ignored (even if the only character?)
*/
{
size_t al = a->name.len
, bl = b->name.len;
while (al > 0 && a->name.ptr[al - 1] == '.')
al--;
while (bl > 0 && b->name.ptr[bl - 1] == '.')
bl--;
return al == bl
&& strncasecmp(a->name.ptr, b->name.ptr, al) == 0;
}
case ID_DER_ASN1_DN:
return same_dn(a->name, b->name);
case ID_KEY_ID:
return a->name.len == b->name.len
&& memeq(a->name.ptr, b->name.ptr, a->name.len);
default:
bad_case(a->kind);
}
return FALSE;
}
/* compare two struct id values, DNs can contain wildcards */
bool match_id(const struct id *a, const struct id *b, int *wildcards)
{
if (b->kind == ID_ANY)
{
*wildcards = MAX_WILDCARDS;
return TRUE;
}
if (a->kind != b->kind)
return FALSE;
if (a->kind == ID_DER_ASN1_DN)
return match_dn(a->name, b->name, wildcards);
else
{
*wildcards = 0;
return same_id(a, b);
}
}
/* count the numer of wildcards in an id */
int id_count_wildcards(const struct id *id)
{
switch (id->kind)
{
case ID_ANY:
return MAX_WILDCARDS;
case ID_DER_ASN1_DN:
return dn_count_wildcards(id->name);
default:
return 0;
}
}
/* build an ID payload
* Note: no memory is allocated for the body of the payload (tl->ptr).
* We assume it will end up being a pointer into a sufficiently
* stable datastructure. It only needs to last a short time.
*/
void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl, struct end *end)
{
const struct id *id = resolve_myid(&end->id);
zero(hd);
hd->isaiid_idtype = id->kind;
switch (id->kind)
{
case ID_ANY:
hd->isaiid_idtype = aftoinfo(addrtypeof(&end->host_addr))->id_addr;
tl->len = addrbytesptr(&end->host_addr
, (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
break;
case ID_FQDN:
case ID_USER_FQDN:
case ID_DER_ASN1_DN:
case ID_KEY_ID:
*tl = id->name;
break;
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
tl->len = addrbytesptr(&id->ip_addr
, (const unsigned char **)&tl->ptr); /* sets tl->ptr too */
break;
default:
bad_case(id->kind);
}
}
/**
* Converts libstrongswan's identification_t type into pluto's struct id
*/
void id_from_identification(struct id *id, identification_t *identification)
{
chunk_t encoding;
encoding = identification->get_encoding(identification);
id->kind = identification->get_type(identification);
switch (id->kind)
{
case ID_FQDN:
case ID_USER_FQDN:
case ID_DER_ASN1_DN:
case ID_KEY_ID:
id->name = encoding;
break;
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
initaddr(encoding.ptr, encoding.len,
(id->kind == ID_IPV4_ADDR) ? AF_INET : AF_INET6,
&id->ip_addr);
break;
case ID_ANY:
default:
id->kind = ID_ANY;
id->name = chunk_empty;
}
}
/*
* Local Variables:
* c-basic-offset:4
* c-style: pluto
* End:
*/
-68
View File
@@ -1,68 +0,0 @@
/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
* Copyright (C) 1999-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef _ID_H
#define _ID_H
#include <utils/identification.h>
#include "defs.h"
struct id {
int kind; /* ID_* value */
ip_address ip_addr; /* ID_IPV4_ADDR, ID_IPV6_ADDR */
chunk_t name; /* ID_FQDN, ID_USER_FQDN (with @) */
/* ID_KEY_ID, ID_DER_ASN_DN */
};
extern void init_id(void);
extern void free_id(void);
extern const struct id empty_id; /* ID_ANY */
enum myid_state {
MYID_UNKNOWN, /* not yet figured out */
MYID_HOSTNAME, /* our current hostname */
MYID_IP, /* our default IP address */
MYID_SPECIFIED /* as specified by ipsec.conf */
};
extern enum myid_state myid_state;
extern struct id myids[MYID_SPECIFIED+1]; /* %myid */
extern char *myid_str[MYID_SPECIFIED+1]; /* strings */
extern void set_myid(enum myid_state s, char *);
extern void show_myid_status(void);
#define resolve_myid(id) ((id)->kind == ID_MYID? &myids[myid_state] : (id))
extern void set_myFQDN(void);
extern err_t atoid(char *src, struct id *id, bool myid_ok);
extern int keyidtoa(char *dst, size_t dstlen, chunk_t keyid);
extern void iptoid(const ip_address *ip, struct id *id);
extern int idtoa(const struct id *id, char *dst, size_t dstlen);
#define IDTOA_BUF 512
extern void escape_metachar(const char *src, char *dst, size_t dstlen);
struct end; /* forward declaration of tag (defined in connections.h) */
extern void unshare_id_content(struct id *id);
extern void free_id_content(struct id *id);
extern bool same_id(const struct id *a, const struct id *b);
#define MAX_WILDCARDS 15
extern bool match_id(const struct id *a, const struct id *b, int *wildcards);
extern int id_count_wildcards(const struct id *id);
#define id_is_ipaddr(id) ((id)->kind == ID_IPV4_ADDR || (id)->kind == ID_IPV6_ADDR)
struct isakmp_ipsec_id; /* forward declaration of tag (defined in packet.h) */
extern void build_id_payload(struct isakmp_ipsec_id *hd, chunk_t *tl,
struct end *end);
extern void id_from_identification(struct id *id, identification_t *identification);
#endif /* _ID_H */
+134 -145
View File
@@ -35,12 +35,14 @@
#include <crypto/rngs/rng.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
#include <utils/identification.h>
#include "constants.h"
#include "defs.h"
#include "myid.h"
#include "state.h"
#include "id.h"
#include "x509.h"
#include "ac.h"
#include "crl.h"
#include "ca.h"
#include "certs.h"
@@ -1569,7 +1571,7 @@ static bool take_a_crack(struct tac_state *s, pubkey_t *kr)
}
}
static stf_status check_signature(key_type_t key_type, const struct id* peer,
static stf_status check_signature(key_type_t key_type, identification_t* peer,
struct state *st, chunk_t hash,
const pb_stream *sig_pbs,
#ifdef USE_KEYRR
@@ -1593,7 +1595,8 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
for (gw = c->gw_info; gw != NULL; gw = gw->next)
{
/* only consider entries that have a key and are for our peer */
if (gw->gw_key_present && same_id(&gw->gw_id, &c->spd.that.id)&&
if (gw->gw_key_present &&
gw->gw_id->equals(gw->gw_id, c->spd.that.id) &&
take_a_crack(&s, gw->key))
{
return STF_OK;
@@ -1611,11 +1614,8 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
{
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
struct id key_id;
id_from_identification(&key_id, key->id);
if (type == key_type && same_id(peer, &key_id))
if (type == key_type && peer->equals(peer, key->id))
{
time_t now = time(NULL);
@@ -1678,31 +1678,27 @@ static stf_status check_signature(key_type_t key_type, const struct id* peer,
/* no acceptable key was found: diagnose */
{
char id_buf[BUF_LEN]; /* arbitrary limit on length of ID reported */
idtoa(peer, id_buf, sizeof(id_buf));
if (s.tried_cnt == 0)
{
loglog(RC_LOG_SERIOUS, "no public key known for '%s'", id_buf);
loglog(RC_LOG_SERIOUS, "no public key known for '%Y'", peer);
}
else if (s.tried_cnt == 1)
{
loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
" wrong key?; tried %d", id_buf, s.tried_cnt);
loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
" wrong key?; tried %d", peer, s.tried_cnt);
DBG(DBG_CONTROL,
DBG_log("public key for '%s' failed: "
"decrypted SIG payload into a malformed ECB", id_buf)
DBG_log("public key for '%Y' failed: "
"decrypted SIG payload into a malformed ECB", peer)
)
}
else
{
loglog(RC_LOG_SERIOUS, "signature check for '%s' failed: "
"tried %d keys but none worked.", id_buf, s.tried_cnt);
loglog(RC_LOG_SERIOUS, "signature check for '%Y' failed: "
"tried %d keys but none worked.", peer, s.tried_cnt);
DBG(DBG_CONTROL,
DBG_log("all %d public keys for '%s' failed: "
DBG_log("all %d public keys for '%Y' failed: "
"best decrypted SIG payload into a malformed ECB",
s.tried_cnt, id_buf)
s.tried_cnt, peer)
)
}
return STF_FAIL + INVALID_KEY_INFORMATION;
@@ -2198,16 +2194,17 @@ static void decode_cert(struct msg_digest *md)
}
else if (cert->isacert_type == CERT_PKCS7_WRAPPED_X509)
{
x509cert_t *x509cert = NULL;
linked_list_t *certs = linked_list_create();
if (pkcs7_parse_signedData(blob, NULL, &x509cert, NULL, NULL))
if (pkcs7_parse_signedData(blob, NULL, certs, NULL, NULL))
{
store_x509certs(&x509cert, strict_crl_policy);
store_x509certs(certs, strict_crl_policy);
}
else
{
plog("Syntax error in PKCS#7 wrapped X.509 certificates");
}
certs->destroy_offset(certs, offsetof(certificate_t, destroy));
}
else
{
@@ -2276,12 +2273,13 @@ static void decode_cr(struct msg_digest *md, connection_t *c)
* We must be called before SIG or HASH are decoded since we
* may change the peer's public key or ID.
*/
static bool decode_peer_id(struct msg_digest *md, struct id *peer)
static bool decode_peer_id(struct msg_digest *md, identification_t **peer)
{
struct state *const st = md->st;
struct payload_digest *const id_pld = md->chain[ISAKMP_NEXT_ID];
const pb_stream *const id_pbs = &id_pld->pbs;
struct isakmp_id *const id = &id_pld->payload.id;
chunk_t id_payload;
/* I think that RFC2407 (IPSEC DOI) 4.6.2 is confused.
* It talks about the protocol ID and Port fields of the ID
@@ -2310,74 +2308,50 @@ static bool decode_peer_id(struct msg_digest *md, struct id *peer)
return FALSE;
}
peer->kind = id->isaid_idtype;
id_payload = chunk_create(id_pbs->cur, pbs_left(id_pbs));
switch (peer->kind)
switch (id->isaid_idtype)
{
case ID_IPV4_ADDR:
case ID_IPV6_ADDR:
/* failure mode for initaddr is probably inappropriate address length */
{
err_t ugh = initaddr(id_pbs->cur, pbs_left(id_pbs)
, peer->kind == ID_IPV4_ADDR? AF_INET : AF_INET6
, &peer->ip_addr);
if (ugh != NULL)
case ID_IPV4_ADDR:
if (id_payload.len != 4)
{
loglog(RC_LOG_SERIOUS, "improper %s identification payload: %s"
, enum_show(&ident_names, peer->kind), ugh);
/* XXX Could send notification back */
loglog(RC_LOG_SERIOUS, "improper %s Phase 1 ID payload",
enum_show(&ident_names, id->isaid_idtype));
return FALSE;
}
}
break;
case ID_USER_FQDN:
if (memchr(id_pbs->cur, '@', pbs_left(id_pbs)) == NULL)
{
loglog(RC_LOG_SERIOUS, "peer's ID_USER_FQDN contains no @");
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;
}
/* 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));
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
+6
View File
@@ -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 */
+31 -7
View File
@@ -45,7 +45,6 @@
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "connections.h"
#include "state.h"
#include "timer.h"
@@ -357,6 +356,33 @@ ipsec_spi_t get_my_cpi(struct spd_route *sr, bool tunnel)
return htonl((ipsec_spi_t)latest_cpi);
}
/* Replace the shell metacharacters ', \, ", `, and $ in a character string
* by escape sequences consisting of their octal values
*/
static void escape_metachar(const char *src, char *dst, size_t dstlen)
{
while (*src != '\0' && dstlen > 4)
{
switch (*src)
{
case '\'':
case '\\':
case '"':
case '`':
case '$':
sprintf(dst,"\\%s%o", (*src < 64)?"0":"", *src);
dst += 4;
dstlen -= 4;
break;
default:
*dst++ = *src;
dstlen--;
}
src++;
}
*dst = '\0';
}
/* invoke the updown script to do the routing and firewall commands required
*
* The user-specified updown script is run. Parameters are fed to it in
@@ -471,7 +497,7 @@ static bool do_command(connection_t *c, struct spd_route *sr,
}
addrtot(&sr->this.host_addr, 0, me_str, sizeof(me_str));
idtoa(&sr->this.id, myid_str, sizeof(myid_str));
snprintf(myid_str, sizeof(myid_str), "%Y", sr->this.id);
escape_metachar(myid_str, secure_myid_str, sizeof(secure_myid_str));
subnettot(&sr->this.client, 0, myclient_str, sizeof(myclientnet_str));
networkof(&sr->this.client, &ta);
@@ -480,7 +506,7 @@ static bool do_command(connection_t *c, struct spd_route *sr,
addrtot(&ta, 0, myclientmask_str, sizeof(myclientmask_str));
addrtot(&sr->that.host_addr, 0, peer_str, sizeof(peer_str));
idtoa(&sr->that.id, peerid_str, sizeof(peerid_str));
snprintf(peerid_str, sizeof(peerid_str), "%Y", sr->that.id);
escape_metachar(peerid_str, secure_peerid_str, sizeof(secure_peerid_str));
subnettot(&sr->that.client, 0, peerclient_str, sizeof(peerclientnet_str));
networkof(&sr->that.client, &ta);
@@ -492,12 +518,10 @@ static bool do_command(connection_t *c, struct spd_route *sr,
{
pubkey_t *key = p->key;
key_type_t type = key->public_key->get_type(key->public_key);
struct id key_id;
int pathlen;
id_from_identification(&key_id, key->id);
if (type == KEY_RSA && same_id(&sr->that.id, &key_id) &&
if (type == KEY_RSA &&
sr->that.id->equals(sr->that.id, key->id) &&
trusted_ca(key->issuer, sr->that.ca, &pathlen))
{
if (key->issuer)
+25 -60
View File
@@ -39,7 +39,6 @@
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "x509.h"
#include "pgpcert.h"
#include "certs.h"
@@ -61,7 +60,7 @@ const char *shared_secrets_file = SHARED_SECRETS_FILE;
typedef struct id_list id_list_t;
struct id_list {
struct id id;
identification_t *id;
id_list_t *next;
};
@@ -109,9 +108,7 @@ static const secret_t* get_secret(const connection_t *c,
unsigned int best_match = 0;
secret_t *best = NULL;
secret_t *s;
const struct id *my_id = &c->spd.this.id
, *his_id = &c->spd.that.id;
struct id rw_id;
identification_t *my_id, *his_id;
/* is there a certificate assigned to this connection? */
if (kind == PPK_PUBKEY && c->spd.this.cert.type != CERT_NONE)
@@ -131,23 +128,24 @@ static const secret_t* get_secret(const connection_t *c,
return best;
}
my_id = c->spd.this.id;
if (his_id_was_instantiated(c))
{
/* roadwarrior: replace him with 0.0.0.0 */
rw_id.kind = c->spd.that.id.kind;
rw_id.name = chunk_empty;
happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
his_id = &rw_id;
his_id = identification_create_from_string("%any");
}
else if (kind == PPK_PSK
&& (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK))
&& ((c->kind == CK_TEMPLATE && c->spd.that.id.kind == ID_ANY) ||
(c->kind == CK_INSTANCE && id_is_ipaddr(&c->spd.that.id))))
else if (kind == PPK_PSK && (c->policy & (POLICY_PSK | POLICY_XAUTH_PSK)) &&
((c->kind == CK_TEMPLATE &&
c->spd.that.id->get_type(c->spd.that.id) == ID_ANY) ||
(c->kind == CK_INSTANCE && id_is_ipaddr(c->spd.that.id))))
{
/* roadwarrior: replace him with 0.0.0.0 */
rw_id.kind = ID_IPV4_ADDR;
happy(anyaddr(addrtypeof(&c->spd.that.host_addr), &rw_id.ip_addr));
his_id = &rw_id;
his_id = identification_create_from_string("%any");
}
else
{
his_id = c->spd.that.id->clone(c->spd.that.id);
}
for (s = secrets; s != NULL; s = s->next)
@@ -170,11 +168,11 @@ static const secret_t* get_secret(const connection_t *c,
for (i = s->ids; i != NULL; i = i->next)
{
if (same_id(my_id, &i->id))
if (my_id->equals(my_id, i->id))
{
match |= match_me;
}
if (same_id(his_id, &i->id))
if (his_id->equals(his_id, i->id))
{
match |= match_him;
}
@@ -240,6 +238,7 @@ static const secret_t* get_secret(const connection_t *c,
}
}
}
his_id->destroy(his_id);
return best;
}
@@ -761,16 +760,12 @@ static void log_psk(secret_t *s)
{
do
{
n += idtoa(&id_list->id, buf + n, BUF_LEN - n);
n += snprintf(buf + n, BUF_LEN - n, "%Y ", id_list->id);
if (n >= BUF_LEN)
{
n = BUF_LEN - 1;
break;
}
else if (n < BUF_LEN - 1)
{
n += snprintf(buf + n, BUF_LEN - n, " ");
}
id_list = id_list->next;
}
while (id_list);
@@ -947,42 +942,12 @@ static void process_secret_records(int whackfd)
/* an id
* See RFC2407 IPsec Domain of Interpretation 4.6.2
*/
struct id id;
err_t ugh;
id_list_t *i = malloc_thing(id_list_t);
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);
}
i->id = identification_create_from_string(tok);
i->next = s->ids;
s->ids = i;
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 = 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)
+1
View File
@@ -38,6 +38,7 @@
#include "server.h"
#include "state.h"
#include "connections.h"
#include "myid.h"
#include "kernel.h"
#include "whack.h" /* needs connections.h */
#include "timer.h"
+2 -1
View File
@@ -1154,7 +1154,8 @@ xauth_inR1(struct msg_digest *md)
peer.conn_name = st->st_connection->name;
addrtot(&md->sender, 0, peer.ip_address, sizeof(peer.ip_address));
idtoa(&md->st->st_connection->spd.that.id, peer.id, sizeof(peer.id));
snprintf(peer.id, sizeof(peer.id), "%Y",
md->st->st_connection->spd.that.id);
DBG(DBG_CONTROL,
DBG_log("peer xauth user name is '%.*s'"
+121
View File
@@ -0,0 +1,121 @@
/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
* Copyright (C) 1999-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#include <errno.h>
#include <unistd.h>
#ifndef HOST_NAME_MAX /* POSIX 1003.1-2001 says <unistd.h> defines this */
# define HOST_NAME_MAX 255 /* upper bound, according to SUSv2 */
#endif
#include <utils/identification.h>
#include <freeswan.h>
#include "myid.h"
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "connections.h"
#include "packet.h"
#include "whack.h"
enum myid_state myid_state = MYID_UNKNOWN;
identification_t *myids[MYID_SPECIFIED+1]; /* %myid */
/**
* Fills in myid from environment variable IPSECmyid or defaultrouteaddr
*/
void init_myid(void)
{
myid_state = MYID_UNKNOWN;
{
enum myid_state s;
for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
{
myids[s] = identification_create_from_string("%any");
}
}
set_myid(MYID_SPECIFIED, getenv("IPSECmyid"));
set_myid(MYID_IP, getenv("defaultrouteaddr"));
set_myFQDN();
}
/**
* Free myid module
*/
void free_myid(void)
{
enum myid_state s;
for (s = MYID_UNKNOWN; s <= MYID_SPECIFIED; s++)
{
myids[s]->destroy(myids[s]);
}
}
void set_myid(enum myid_state s, char *idstr)
{
if (idstr)
{
myids[s]->destroy(myids[s]);
myids[s] = identification_create_from_string(idstr);
if (s == MYID_SPECIFIED)
{
myid_state = MYID_SPECIFIED;
}
}
}
void set_myFQDN(void)
{
char FQDN[HOST_NAME_MAX + 1];
int r = gethostname(FQDN, sizeof(FQDN));
size_t len;
if (r != 0)
{
log_errno((e, "gethostname() failed in set_myFQDN"));
}
else
{
FQDN[sizeof(FQDN) - 1] = '\0'; /* insurance */
len = strlen(FQDN);
if (len > 0 && FQDN[len-1] == '.')
{
/* nuke trailing . */
FQDN[len-1] = '\0';
}
if (!strcaseeq(FQDN, "localhost.localdomain"))
{
myids[MYID_HOSTNAME]->destroy(myids[MYID_HOSTNAME]);
myids[MYID_HOSTNAME] = identification_create_from_string(FQDN);
}
}
}
void show_myid_status(void)
{
whack_log(RC_COMMENT, "%%myid = '%Y'", myids[myid_state]);
}
/*
* Local Variables:
* c-basic-offset:4
* c-style: pluto
* End:
*/
+38
View File
@@ -0,0 +1,38 @@
/* identity representation, as in IKE ID Payloads (RFC 2407 DOI 4.6.2.1)
* Copyright (C) 1999-2001 D. Hugh Redelmeier
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* for more details.
*/
#ifndef _MYID_H
#define _MYID_H
#include <utils/identification.h>
extern void init_myid(void);
extern void free_myid(void);
enum myid_state {
MYID_UNKNOWN, /* not yet figured out */
MYID_HOSTNAME, /* our current hostname */
MYID_IP, /* our default IP address */
MYID_SPECIFIED /* as specified by ipsec.conf */
};
extern enum myid_state myid_state;
extern identification_t* myids[MYID_SPECIFIED+1]; /* %myid */
extern void set_myid(enum myid_state s, char *);
extern void show_myid_status(void);
extern void set_myFQDN(void);
#define resolve_myid(id) ((id)->get_type(id) == ID_MYID? myids[myid_state] : (id))
#endif /* _MYID_H */
+4 -5
View File
@@ -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);
}
/**
+2 -1
View File
@@ -17,6 +17,7 @@
#ifndef _PGPCERT_H
#define _PGPCERT_H
#include <utils/identification.h>
#include <crypto/hashers/hasher.h>
#include <credentials/keys/private_key.h>
#include <credentials/keys/public_key.h>
@@ -46,7 +47,7 @@ struct pgpcert {
extern const pgpcert_t pgpcert_empty;
extern bool parse_pgp(chunk_t blob, pgpcert_t *cert);
extern void share_pgpcert(pgpcert_t *cert);
extern void select_pgpcert_id(pgpcert_t *cert, struct id *end_id);
extern identification_t* select_pgpcert_id(pgpcert_t *cert, identification_t *id);
extern pgpcert_t* add_pgpcert(pgpcert_t *cert);
extern void list_pgp_end_certs(bool utc);
extern void release_pgpcert(pgpcert_t *cert);
+26 -32
View File
@@ -19,8 +19,6 @@
#include <string.h>
#include <time.h>
#include <freeswan.h>
#include <library.h>
#include <debug.h>
#include <asn1/asn1.h>
@@ -28,11 +26,8 @@
#include <asn1/oid.h>
#include <crypto/rngs/rng.h>
#include <crypto/crypters/crypter.h>
#include <credentials/certificates/x509.h>
#include "constants.h"
#include "defs.h"
#include "x509.h"
#include "certs.h"
#include "pkcs7.h"
const contentInfo_t empty_contentInfo = {
@@ -170,7 +165,8 @@ end:
/**
* Parse a PKCS#7 signedData object
*/
bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert,
bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
linked_list_t *certs,
chunk_t *attributes, certificate_t *cacert)
{
asn1_parser_t *parser;
@@ -218,24 +214,17 @@ bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data, x509cert_t **cert
}
break;
case PKCS7_SIGNED_CERT:
if (cert != NULL)
{
x509cert_t *newcert = malloc_thing(x509cert_t);
certificate_t *cert;
DBG2(" parsing pkcs7-wrapped certificate");
*newcert = empty_x509cert;
newcert->cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
BUILD_END);
if (newcert->cert)
cert = lib->creds->create(lib->creds,
CRED_CERTIFICATE, CERT_X509,
BUILD_BLOB_ASN1_DER, object,
BUILD_END);
if (cert)
{
newcert->next = *cert;
*cert = newcert;
}
else
{
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)
+2 -3
View File
@@ -18,11 +18,10 @@
#ifndef _PKCS7_H
#define _PKCS7_H
#include <utils/linked_list.h>
#include <crypto/crypters/crypter.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/certificate.h>
#include "defs.h"
#include "x509.h"
/* Access structure for a PKCS#7 ContentInfo object */
@@ -38,7 +37,7 @@ extern const contentInfo_t empty_contentInfo;
extern bool pkcs7_parse_contentInfo(chunk_t blob, u_int level0,
contentInfo_t *cInfo);
extern bool pkcs7_parse_signedData(chunk_t blob, contentInfo_t *data,
x509cert_t **cert, chunk_t *attributes,
linked_list_t *cert, chunk_t *attributes,
certificate_t *cacert);
extern bool pkcs7_parse_envelopedData(chunk_t blob, chunk_t *data,
chunk_t serialNumber, private_key_t *key);
+3 -3
View File
@@ -48,7 +48,7 @@
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "myid.h"
#include "ca.h"
#include "certs.h"
#include "ac.h"
@@ -673,7 +673,7 @@ int main(int argc, char **argv)
init_demux();
init_kernel();
init_adns();
init_id();
init_myid();
init_fetch();
/* drop unneeded capabilities and change UID/GID */
@@ -762,7 +762,7 @@ void exit_pluto(int status)
stop_adns();
free_md_pool();
free_crypto();
free_id(); /* free myids */
free_myid(); /* free myids */
free_events(); /* free remaining events */
free_vendorid(); /* free all vendor id records */
free_builder();
+56 -67
View File
@@ -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)
/* 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++)
{
delete_public_keys(key_id, msg->pubkey_alg, NULL, chunk_empty);
}
if (msg->keyval.len == 0)
{
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
+4 -6
View File
@@ -24,7 +24,6 @@
#include "constants.h"
#include "defs.h"
#include "id.h"
#include "connections.h"
#include "state.h"
#include "packet.h"
@@ -835,19 +834,18 @@ static err_t find_preshared_key(struct state* st)
if (get_preshared_secret(c) == NULL)
{
char my_id[BUF_LEN], his_id[BUF_LEN];
char his_id[BUF_LEN];
idtoa(&c->spd.this.id, my_id, sizeof(my_id));
if (his_id_was_instantiated(c))
{
strcpy(his_id, "%any");
}
else
{
idtoa(&c->spd.that.id, his_id, sizeof(his_id));
snprintf(his_id, sizeof(his_id), "%Y", c->spd.that.id);
}
ugh = builddiag("Can't authenticate: no preshared key found for `%s' and `%s'"
, my_id, his_id);
ugh = builddiag("Can't authenticate: no preshared key found "
"for '%Y' and '%s'", c->spd.this.id, his_id);
}
return ugh;
}
+1
View File
@@ -21,6 +21,7 @@
#include <crypto/diffie_hellman.h>
#include "defs.h"
#include "connections.h"
/* Message ID mechanism.
+50 -735
View File
@@ -26,8 +26,6 @@
#include <freeswan.h>
#include <asn1/asn1.h>
#include <asn1/asn1_parser.h>
#include <asn1/oid.h>
#include <crypto/hashers/hasher.h>
#include <utils/enumerator.h>
#include <utils/identification.h>
@@ -35,7 +33,6 @@
#include "constants.h"
#include "defs.h"
#include "log.h"
#include "id.h"
#include "x509.h"
#include "crl.h"
#include "ca.h"
@@ -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);
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);
}
}
else
{
plog("X.509 certificate rejected");
}
*pp = cert->next;
free_x509cert(cert);
}
enumerator->destroy(enumerator);
}
/**
+3 -8
View File
@@ -19,12 +19,12 @@
#define _X509_H
#include <utils/identification.h>
#include <utils/linked_list.h>
#include <credentials/keys/public_key.h>
#include <credentials/keys/private_key.h>
#include <credentials/certificates/x509.h>
#include "constants.h"
#include "id.h"
/* access structure for an X.509v3 certificate */
@@ -41,12 +41,7 @@ struct x509cert {
extern const x509cert_t empty_x509cert;
extern bool same_keyid(chunk_t a, chunk_t b);
extern bool same_dn(chunk_t a, chunk_t b);
extern bool match_dn(chunk_t a, chunk_t b, int *wildcards);
extern int dn_count_wildcards(chunk_t dn);
extern int dntoa(char *dst, size_t dstlen, chunk_t dn);
extern err_t atodn(char *src, chunk_t *dn);
extern void select_x509cert_id(x509cert_t *cert, struct id *end_id);
extern identification_t* select_x509cert_id(x509cert_t *cert, identification_t *id);
extern void parse_authorityKeyIdentifier(chunk_t blob, int level0,
chunk_t *authKeyID,
chunk_t *authKeySerialNumber);
@@ -60,7 +55,7 @@ extern x509cert_t* get_x509cert(identification_t *issuer, chunk_t keyid, x509cer
extern void share_x509cert(x509cert_t *cert);
extern void release_x509cert(x509cert_t *cert);
extern void free_x509cert(x509cert_t *cert);
extern void store_x509certs(x509cert_t **firstcert, bool strict);
extern void store_x509certs(linked_list_t *certs, bool strict);
extern void list_x509cert_chain(const char *caption, x509cert_t* cert,
x509_flag_t flags, bool utc);
extern void list_x509_end_certs(bool utc);
+1 -31
View File
@@ -24,8 +24,7 @@ LIBSTRONGSWANBUILDDIR=$(top_builddir)/src/libstrongswan
LIBFREESWANBUILDDIR=$(top_builddir)/src/libfreeswan
scepclient_LDADD = \
ca.o crl.o certs.o constants.o defs.o fetch.o id.o keys.o lex.o \
ocsp.o pgpcert.o pkcs7.o smartcard.o x509.o \
constants.o defs.o lex.o pkcs7.o \
$(LIBSTRONGSWANBUILDDIR)/libstrongswan.la \
$(LIBFREESWANBUILDDIR)/libfreeswan.a
@@ -37,44 +36,15 @@ endif
dist_man_MANS = scepclient.8
ca.o : $(PLUTODIR)/ca.c $(PLUTODIR)/ca.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
certs.o : $(PLUTODIR)/certs.c $(PLUTODIR)/certs.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
constants.o : $(PLUTODIR)/constants.c $(PLUTODIR)/constants.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
crl.o : $(PLUTODIR)/crl.c $(PLUTODIR)/crl.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
defs.o : $(PLUTODIR)/defs.c $(PLUTODIR)/defs.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
fetch.o : $(PLUTODIR)/fetch.c $(PLUTODIR)/fetch.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
id.o : $(PLUTODIR)/id.c $(PLUTODIR)/id.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
keys.o : $(PLUTODIR)/keys.c $(PLUTODIR)/keys.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
lex.o : $(PLUTODIR)/lex.c $(PLUTODIR)/lex.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
ocsp.o : $(PLUTODIR)/ocsp.c $(PLUTODIR)/ocsp.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
pgpcert.o : $(PLUTODIR)/pgpcert.c $(PLUTODIR)/pgpcert.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
pkcs7.o : $(PLUTODIR)/pkcs7.c $(PLUTODIR)/pkcs7.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
smartcard.o : $(PLUTODIR)/smartcard.c $(PLUTODIR)/smartcard.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
x509.o : $(PLUTODIR)/x509.c $(PLUTODIR)/x509.h
$(COMPILE) $(INCLUDES) -c -o $@ $<
+13 -11
View File
@@ -54,8 +54,8 @@
#include "../pluto/constants.h"
#include "../pluto/defs.h"
#include "../pluto/log.h"
#include "../pluto/pkcs7.h"
#include "../pluto/certs.h"
#include "../pluto/pkcs7.h"
#include "scep.h"
@@ -789,10 +789,10 @@ int main(int argc, char **argv)
*/
if (filetype_in & PKCS1) /* load an RSA key pair from file */
{
prompt_pass_t pass = { "", FALSE, STDIN_FILENO };
char *path = concatenate_paths(PRIVATE_KEY_PATH, file_in_pkcs1);
private_key = load_private_key(path, &pass, KEY_RSA);
private_key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_RSA,
BUILD_FROM_FILE, path, BUILD_END);
}
else /* generate an RSA key pair */
{
@@ -1020,10 +1020,12 @@ int main(int argc, char **argv)
*/
if (filetype_out & CERT)
{
certificate_t *cert;
enumerator_t *enumerator;
char *path = concatenate_paths(CA_CERT_PATH, file_in_cacert_sig);
time_t poll_start = 0;
x509cert_t *certs = NULL;
linked_list_t *certs = linked_list_create();
chunk_t envelopedData = chunk_empty;
chunk_t certData = chunk_empty;
contentInfo_t data = empty_contentInfo;
@@ -1115,7 +1117,7 @@ int main(int argc, char **argv)
{
exit_scepclient("could not decrypt envelopedData");
}
if (!pkcs7_parse_signedData(certData, NULL, &certs, NULL, NULL))
if (!pkcs7_parse_signedData(certData, NULL, certs, NULL, NULL))
{
exit_scepclient("error parsing the scep response");
}
@@ -1123,11 +1125,12 @@ int main(int argc, char **argv)
/* store the end entity certificate */
path = concatenate_paths(HOST_CERT_PATH, file_out_cert);
while (certs != NULL)
enumerator = certs->create_enumerator(certs);
while (enumerator->enumerate(enumerator, &cert))
{
bool stored = FALSE;
x509cert_t *cert = certs;
x509_t *x509 = (x509_t*)cert->cert;
x509_t *x509 = (x509_t*)cert;
if (!(x509->get_flags(x509) & X509_CA))
{
@@ -1135,7 +1138,7 @@ int main(int argc, char **argv)
{
exit_scepclient("multiple certs received, only first stored");
}
encoding = cert->cert->get_encoding(cert->cert);
encoding = cert->get_encoding(cert);
if (!chunk_write(encoding, path, "requested cert", 0022, force))
{
exit_scepclient("could not write cert file '%s'", path);
@@ -1143,9 +1146,8 @@ int main(int argc, char **argv)
chunk_free(&encoding);
stored = TRUE;
}
certs = certs->next;
free_x509cert(cert);
}
certs->destroy_offset(certs, offsetof(certificate_t, destroy));
filetype_out &= ~CERT; /* delete CERT flag */
}
+2
View File
@@ -17,6 +17,8 @@
#include <freeswan.h>
#include <defs.h>
/* copy of smartcard operations, defined in smartcard.h */
#ifndef SC_OP_T
#define SC_OP_T