identification_t *other_id;
/**
+ * we have a cert issued by this CA
+ */
+ identification_t *my_ca;
+
+ /**
+ * we require the other end to have a cert issued by this CA
+ */
+ identification_t *other_ca;
+
+ /**
* list for all proposals
*/
linked_list_t *proposals;
}
/**
+ * Implementation of policy_t.add_authorities
+ */
+static void add_authorities(private_policy_t *this, identification_t *my_ca, identification_t *other_ca)
+{
+ this->my_ca = my_ca;
+ this->other_ca = other_ca;
+}
+
+/**
* Implementation of policy_t.add_my_traffic_selector
*/
static void add_my_traffic_selector(private_policy_t *this, traffic_selector_t *traffic_selector)
proposal_t *proposal;
traffic_selector_t *ts;
+ /* clone the certification authorities */
+ clone->my_ca = this->my_ca->clone(this->my_ca);
+ clone->other_ca = this->other_ca->clone(this->other_ca);
+
/* clone all proposals */
iterator = this->proposals->create_iterator(this->proposals, TRUE);
while (iterator->has_next(iterator))
}
this->other_ts->destroy(this->other_ts);
+ /* delete certification authorities */
+ this->my_ca->destroy(this->my_ca);
+ this->other_ca->destroy(this->other_ca);
+
/* delete ids */
this->my_id->destroy(this->my_id);
this->other_id->destroy(this->other_id);
this->public.add_my_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_my_traffic_selector;
this->public.add_other_traffic_selector = (void(*)(policy_t*,traffic_selector_t*))add_other_traffic_selector;
this->public.add_proposal = (void(*)(policy_t*,proposal_t*))add_proposal;
+ this->public.add_authorities = (void(*)(policy_t*,identification_t*, identification_t*))add_authorities;
this->public.get_soft_lifetime = (u_int32_t (*) (policy_t *))get_soft_lifetime;
this->public.get_hard_lifetime = (u_int32_t (*) (policy_t *))get_hard_lifetime;
this->public.clone = (policy_t*(*)(policy_t*))clone;
this->public.destroy = (void(*)(policy_t*))destroy;
/* apply init values */
+ this->name = strdup(name);
this->my_id = my_id;
this->other_id = other_id;
- this->name = strdup(name);
- /* init private members*/
+ /* initialize private members*/
+ this->my_ca = NULL;
+ this->other_ca = NULL;
this->select_traffic_selectors = select_traffic_selectors;
this->proposals = linked_list_create();
this->my_ts = linked_list_create();
void (*add_proposal) (policy_t *this, proposal_t *proposal);
/**
+ * @brief Add certification authorities
+ *
+ * @param this calling object
+ * @param my_ca issuer of my certificate
+ * @param other_ca required issuer of the peer's certificate
+ */
+ void (*add_authorities) (policy_t *this, identification_t *my_ca, identification_t *other_ca);
+
+ /**
* @brief Get the lifetime of a policy, before rekeying starts.
*
* A call to this function automatically adds a jitter to
int socket;
/**
- * Thread which reads from the socket
+ * Thread which reads from the \ 1ocket
*/
pthread_t assigned_thread;
/**
* Load end entitity certificate
*/
-static void load_end_certificate(const char *filename, identification_t **idp)
+static void load_end_certificate(const char *filename, identification_t **idp, logger_t *logger)
{
char path[PATH_BUF];
x509_t *cert;
identification_t *id = *idp;
identification_t *subject = cert->get_subject(cert);
+ err_t ugh = cert->is_valid(cert, NULL);
+
+ if (ugh != NULL)
+ {
+ logger->log(logger, ERROR, "warning: certificate %s", ugh);
+ }
if (!id->equals(id, subject) && !cert->equals_subjectAltName(cert, id))
{
id->destroy(id);
{
connection_t *connection;
policy_t *policy;
- identification_t *my_id, *other_id;
+ identification_t *my_id, *other_id, *my_ca, *other_ca;
host_t *my_host, *other_host, *my_subnet, *other_subnet;
proposal_t *proposal;
traffic_selector_t *my_ts, *other_ts;
pop_string(msg, &msg->add_conn.name);
pop_string(msg, &msg->add_conn.me.address);
pop_string(msg, &msg->add_conn.other.address);
+ pop_string(msg, &msg->add_conn.me.subnet);
+ pop_string(msg, &msg->add_conn.other.subnet);
pop_string(msg, &msg->add_conn.me.id);
pop_string(msg, &msg->add_conn.other.id);
pop_string(msg, &msg->add_conn.me.cert);
pop_string(msg, &msg->add_conn.other.cert);
- pop_string(msg, &msg->add_conn.me.subnet);
- pop_string(msg, &msg->add_conn.other.subnet);
+ pop_string(msg, &msg->add_conn.me.ca);
+ pop_string(msg, &msg->add_conn.other.ca);
this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name);
return;
}
+ /* TODO check for %same */
+ my_ca = identification_create_from_string(msg->add_conn.me.ca);
+ other_ca = identification_create_from_string(msg->add_conn.other.ca);
+
my_ts = traffic_selector_create_from_subnet(my_subnet, msg->add_conn.me.subnet ?
msg->add_conn.me.subnet_mask : 32);
my_subnet->destroy(my_subnet);
this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching");
host_t *tmp_host;
- identification_t *tmp_id;
+ identification_t *tmp_id, *tmp_ca;
traffic_selector_t *tmp_ts;
char *tmp_cert;
my_id = other_id;
other_id = tmp_id;
+ tmp_ca = my_ca;
+ my_ca = other_ca;
+ other_ca = tmp_ca;
+
tmp_ts = my_ts;
my_ts = other_ts;
other_ts = tmp_ts;
if (msg->add_conn.me.cert)
{
- load_end_certificate(msg->add_conn.me.cert, &my_id);
+ load_end_certificate(msg->add_conn.me.cert, &my_id, this->stroke_logger);
}
if (msg->add_conn.other.cert)
{
- load_end_certificate(msg->add_conn.other.cert, &other_id);
+ load_end_certificate(msg->add_conn.other.cert, &other_id, this->stroke_logger);
}
connection = connection_create(msg->add_conn.name, msg->add_conn.ikev2,
policy->add_proposal(policy, proposal);
policy->add_my_traffic_selector(policy, my_ts);
policy->add_other_traffic_selector(policy, other_ts);
+ policy->add_authorities(policy, my_ca, other_ca);
/* add to global policy list */
charon->policies->add_policy(charon->policies, policy);
/**
+ * Certificate sending policy
+ */
+typedef enum certpolicy {
+ CERT_ALWAYS_SEND = 0,
+ CERT_SEND_IF_ASKED = 1,
+ CERT_NEVER_SEND = 2,
+
+ CERT_YES_SEND = 3, /* synonym for CERT_ALWAYS_SEND */
+ CERT_NO_SEND = 4 /* synonym for CERT_NEVER_SEND */
+} certpolicy_t;
+
+/**
* String mappings for type status_t.
*/
extern mapping_t status_m[];
cfg->conn_default.left.seen = LEMPTY;
cfg->conn_default.right.seen = LEMPTY;
+ cfg->conn_default.left.sendcert = CERT_SEND_IF_ASKED;
+ cfg->conn_default.right.sendcert = CERT_SEND_IF_ASKED;
+
anyaddr(AF_INET, &cfg->conn_default.left.addr);
anyaddr(AF_INET, &cfg->conn_default.left.nexthop);
anyaddr(AF_INET, &cfg->conn_default.left.srcip);
return conn->name;
}
+static void starter_stroke_add_end(stroke_msg_t *msg, stroke_end_t *msg_end, starter_end_t *conn_end)
+{
+ msg_end->id = push_string(msg, conn_end->id);
+ msg_end->cert = push_string(msg, conn_end->cert);
+ msg_end->cert = push_string(msg, conn_end->cert);
+ msg_end->address = push_string(msg, inet_ntoa(conn_end->addr.u.v4.sin_addr));
+ msg_end->subnet = push_string(msg, inet_ntoa(conn_end->subnet.addr.u.v4.sin_addr));
+ msg_end->subnet_mask = conn_end->subnet.maskbits;
+ msg_end->sendcert = conn_end->sendcert;
+}
+
int starter_stroke_add_conn(starter_conn_t *conn)
{
stroke_msg_t msg;
msg.add_conn.ikev2 = conn->keyexchange == KEY_EXCHANGE_IKEV2;
msg.add_conn.name = push_string(&msg, connection_name(conn));
- msg.add_conn.me.id = push_string(&msg, conn->left.id);
- msg.add_conn.me.cert = push_string(&msg, conn->left.cert);
- msg.add_conn.me.address = push_string(&msg, inet_ntoa(conn->left.addr.u.v4.sin_addr));
- msg.add_conn.me.subnet = push_string(&msg, inet_ntoa(conn->left.subnet.addr.u.v4.sin_addr));
- msg.add_conn.me.subnet_mask = conn->left.subnet.maskbits;
-
- msg.add_conn.other.id = push_string(&msg, conn->right.id);
- msg.add_conn.other.cert = push_string(&msg, conn->right.cert);
- msg.add_conn.other.address = push_string(&msg, inet_ntoa(conn->right.addr.u.v4.sin_addr));
- msg.add_conn.other.subnet = push_string(&msg, inet_ntoa(conn->right.subnet.addr.u.v4.sin_addr));
- msg.add_conn.other.subnet_mask = conn->right.subnet.maskbits;
+ starter_stroke_add_end(&msg, &msg.add_conn.me, &conn->right);
+ starter_stroke_add_end(&msg, &msg.add_conn.other, &conn->left);
return send_stroke_msg(&msg);
}
#include <stdio.h>
#include <linux/stddef.h>
+#include <types.h>
+
#include "stroke.h"
#define streq(a, b) (strcmp((a), (b)) == 0) /* clearer shorthand */
msg.add_conn.me.subnet = push_string(&msg, my_net);
msg.add_conn.me.subnet_mask = my_netmask;
msg.add_conn.me.cert = NULL;
+ msg.add_conn.me.ca = NULL;
+ msg.add_conn.me.sendcert = CERT_SEND_IF_ASKED;
msg.add_conn.other.id = push_string(&msg, other_id);
msg.add_conn.other.address = push_string(&msg, other_addr);
msg.add_conn.other.subnet = push_string(&msg, other_net);
msg.add_conn.other.subnet_mask = other_netmask;
msg.add_conn.other.cert = NULL;
+ msg.add_conn.other.ca = NULL;
+ msg.add_conn.other.sendcert = CERT_SEND_IF_ASKED;
return send_stroke_msg(&msg);
}
#define STROKE_BUF_LEN 2048
+typedef struct stroke_end_t stroke_end_t;
+
+struct stroke_end_t {
+ char *id;
+ char *cert;
+ char *ca;
+ char *address;
+ char *subnet;
+ int subnet_mask;
+ certpolicy_t sendcert;
+};
+
typedef struct stroke_msg_t stroke_msg_t;
/**
/* data for STR_ADD_CONN */
struct {
char *name;
- /* is this connection handled by charon? */
- int ikev2;
- struct {
- char *id;
- char *cert;
- char *address;
- char *subnet;
- int subnet_mask;
- } me, other;
+ bool ikev2;
+ stroke_end_t me, other;
} add_conn;
struct {