support of certreq payload in IKE_AUTH messages
This commit is contained in:
@@ -115,6 +115,15 @@ struct credential_store_t {
|
|||||||
*/
|
*/
|
||||||
x509_t* (*get_ca_certificate) (credential_store_t *this, identification_t *id);
|
x509_t* (*get_ca_certificate) (credential_store_t *this, identification_t *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Returns the ca certificate of a specific keyID.
|
||||||
|
*
|
||||||
|
* @param this calling object
|
||||||
|
* @param keyid identification_t object identifiying the cacert.
|
||||||
|
* @return certificate, or NULL if not found
|
||||||
|
*/
|
||||||
|
x509_t* (*get_ca_certificate_by_keyid) (credential_store_t *this, chunk_t keyid);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the ca certificate of a specific subject distinguished name.
|
* @brief Returns the ca certificate of a specific subject distinguished name.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -330,6 +330,7 @@ static x509_t* get_ca_certificate(private_local_credential_store_t *this,
|
|||||||
x509_t *current_cert;
|
x509_t *current_cert;
|
||||||
|
|
||||||
iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
|
iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
|
||||||
|
|
||||||
while (iterator->iterate(iterator, (void**)¤t_cert))
|
while (iterator->iterate(iterator, (void**)¤t_cert))
|
||||||
{
|
{
|
||||||
if (id->equals(id, current_cert->get_subject(current_cert)))
|
if (id->equals(id, current_cert->get_subject(current_cert)))
|
||||||
@@ -342,6 +343,33 @@ static x509_t* get_ca_certificate(private_local_credential_store_t *this,
|
|||||||
|
|
||||||
return found;
|
return found;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implementation of credential_store_t.get_ca_certificate_by_keyid.
|
||||||
|
*/
|
||||||
|
static x509_t* get_ca_certificate_by_keyid(private_local_credential_store_t *this,
|
||||||
|
chunk_t keyid)
|
||||||
|
{
|
||||||
|
x509_t *found = NULL;
|
||||||
|
x509_t *current_cert;
|
||||||
|
|
||||||
|
iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
|
||||||
|
|
||||||
|
while (iterator->iterate(iterator, (void**)¤t_cert))
|
||||||
|
{
|
||||||
|
rsa_public_key_t *pubkey = current_cert->get_public_key(current_cert);
|
||||||
|
|
||||||
|
if (chunk_equals(keyid, pubkey->get_keyid(pubkey)))
|
||||||
|
{
|
||||||
|
found = current_cert;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
return found;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of credential_store_t.get_issuer_certificate.
|
* Implementation of credential_store_t.get_issuer_certificate.
|
||||||
*/
|
*/
|
||||||
@@ -352,6 +380,7 @@ static x509_t* get_issuer_certificate(private_local_credential_store_t *this,
|
|||||||
x509_t *current_cert;
|
x509_t *current_cert;
|
||||||
|
|
||||||
iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
|
iterator_t *iterator = this->ca_certs->create_iterator(this->ca_certs, TRUE);
|
||||||
|
|
||||||
while (iterator->iterate(iterator, (void**)¤t_cert))
|
while (iterator->iterate(iterator, (void**)¤t_cert))
|
||||||
{
|
{
|
||||||
if (cert->is_issuer(cert, current_cert))
|
if (cert->is_issuer(cert, current_cert))
|
||||||
@@ -1096,6 +1125,7 @@ local_credential_store_t * local_credential_store_create(bool strict)
|
|||||||
this->public.credential_store.get_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key;
|
this->public.credential_store.get_trusted_public_key = (rsa_public_key_t*(*)(credential_store_t*,identification_t*))get_trusted_public_key;
|
||||||
this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
|
this->public.credential_store.get_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_certificate;
|
||||||
this->public.credential_store.get_ca_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_ca_certificate;
|
this->public.credential_store.get_ca_certificate = (x509_t* (*) (credential_store_t*,identification_t*))get_ca_certificate;
|
||||||
|
this->public.credential_store.get_ca_certificate_by_keyid = (x509_t* (*) (credential_store_t*,identification_t*))get_ca_certificate_by_keyid;
|
||||||
this->public.credential_store.get_issuer_certificate = (x509_t* (*) (credential_store_t*,const x509_t*))get_issuer_certificate;
|
this->public.credential_store.get_issuer_certificate = (x509_t* (*) (credential_store_t*,const x509_t*))get_issuer_certificate;
|
||||||
this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
|
this->public.credential_store.verify = (bool (*) (credential_store_t*,x509_t*,bool*))verify;
|
||||||
this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
|
this->public.credential_store.add_end_certificate = (x509_t* (*) (credential_store_t*,x509_t*))add_end_certificate;
|
||||||
|
|||||||
@@ -22,6 +22,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <daemon.h>
|
||||||
|
#include <crypto/hashers/hasher.h>
|
||||||
|
|
||||||
#include "certreq_payload.h"
|
#include "certreq_payload.h"
|
||||||
|
|
||||||
@@ -262,12 +266,56 @@ certreq_payload_t *certreq_payload_create()
|
|||||||
/*
|
/*
|
||||||
* Described in header
|
* Described in header
|
||||||
*/
|
*/
|
||||||
certreq_payload_t *certreq_payload_create_from_x509(x509_t *cert)
|
certreq_payload_t *certreq_payload_create_from_cacert(identification_t *id)
|
||||||
{
|
{
|
||||||
|
x509_t *cacert = charon->credentials->get_ca_certificate(charon->credentials, id);
|
||||||
|
rsa_public_key_t *pubkey = cacert->get_public_key(cacert);
|
||||||
|
chunk_t keyid = pubkey->get_keyid(pubkey);
|
||||||
|
|
||||||
certreq_payload_t *this = certreq_payload_create();
|
certreq_payload_t *this = certreq_payload_create();
|
||||||
rsa_public_key_t *pubkey = cert->get_public_key(cert);
|
|
||||||
|
DBG1(DBG_IKE, "request certificate issued by '%D'", id);
|
||||||
|
DBG2(DBG_IKE, " with keyid %#B", &keyid);
|
||||||
|
|
||||||
this->set_cert_encoding(this, CERT_X509_SIGNATURE);
|
this->set_cert_encoding(this, CERT_X509_SIGNATURE);
|
||||||
this->set_data(this, pubkey->get_keyid(pubkey));
|
this->set_data(this, keyid);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Described in header
|
||||||
|
*/
|
||||||
|
certreq_payload_t *certreq_payload_create_from_cacerts(void)
|
||||||
|
{
|
||||||
|
certreq_payload_t *this;
|
||||||
|
chunk_t keyids;
|
||||||
|
u_char *pos;
|
||||||
|
x509_t *cacert;
|
||||||
|
|
||||||
|
iterator_t *iterator = charon->credentials->create_cacert_iterator(charon->credentials);
|
||||||
|
int count = iterator->get_count(iterator);
|
||||||
|
|
||||||
|
if (count == 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
this = certreq_payload_create();
|
||||||
|
keyids = chunk_alloc(count * HASH_SIZE_SHA1);
|
||||||
|
pos = keyids.ptr;
|
||||||
|
|
||||||
|
while (iterator->iterate(iterator, (void**)&cacert))
|
||||||
|
{
|
||||||
|
rsa_public_key_t *pubkey = cacert->get_public_key(cacert);
|
||||||
|
chunk_t keyid = pubkey->get_keyid(pubkey);
|
||||||
|
|
||||||
|
DBG1(DBG_IKE, "request certificate issued by '%D'", cacert->get_subject(cacert));
|
||||||
|
DBG2(DBG_IKE, " with keyid %#B", &keyid);
|
||||||
|
memcpy(pos, keyid.ptr, keyid.len);
|
||||||
|
pos += HASH_SIZE_SHA1;
|
||||||
|
}
|
||||||
|
iterator->destroy(iterator);
|
||||||
|
|
||||||
|
this->set_cert_encoding(this, CERT_X509_SIGNATURE);
|
||||||
|
this->set_data(this, keyids);
|
||||||
|
free(keyids.ptr);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -123,13 +123,22 @@ struct certreq_payload_t {
|
|||||||
certreq_payload_t *certreq_payload_create(void);
|
certreq_payload_t *certreq_payload_create(void);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Creates a certreq_payload_t object from a X.509 CA certificate.
|
* @brief Creates a certreq_payload_t object from a ca certificate
|
||||||
*
|
*
|
||||||
* @param cert X.509 CA certificate
|
* @param id subject distinguished name of CA certificate
|
||||||
* @return certreq_payload_t object
|
* @return certreq_payload_t object
|
||||||
*
|
*
|
||||||
* @ingroup payloads
|
* @ingroup payloads
|
||||||
*/
|
*/
|
||||||
certreq_payload_t *certreq_payload_create_from_x509(x509_t *cert);
|
certreq_payload_t *certreq_payload_create_from_cacert(identification_t *id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Creates a certreq_payload_t object from all ca certificates
|
||||||
|
*
|
||||||
|
* @return certreq_payload_t object
|
||||||
|
*
|
||||||
|
* @ingroup payloads
|
||||||
|
*/
|
||||||
|
certreq_payload_t *certreq_payload_create_from_cacerts(void);
|
||||||
|
|
||||||
#endif /* CERTREQ_PAYLOAD_H_ */
|
#endif /* CERTREQ_PAYLOAD_H_ */
|
||||||
|
|||||||
@@ -225,19 +225,14 @@ static status_t get_request(private_ike_auth_t *this, message_t **result)
|
|||||||
if (this->connection->get_certreq_policy(this->connection) != CERT_NEVER_SEND)
|
if (this->connection->get_certreq_policy(this->connection) != CERT_NEVER_SEND)
|
||||||
{
|
{
|
||||||
certreq_payload_t *certreq_payload;
|
certreq_payload_t *certreq_payload;
|
||||||
|
|
||||||
identification_t *other_ca = this->policy->get_other_ca(this->policy);
|
identification_t *other_ca = this->policy->get_other_ca(this->policy);
|
||||||
|
|
||||||
if (other_ca->get_type(other_ca) == ID_ANY)
|
certreq_payload = (other_ca->get_type(other_ca) == ID_ANY)
|
||||||
{
|
? certreq_payload_create_from_cacerts()
|
||||||
|
: certreq_payload_create_from_cacert(other_ca);
|
||||||
|
|
||||||
}
|
if (certreq_payload != NULL)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
x509_t *cacert = charon->credentials->get_ca_certificate(charon->credentials, other_ca);
|
|
||||||
|
|
||||||
DBG2(DBG_IKE, "certreq with ca: '%D'", other_ca);
|
|
||||||
certreq_payload = certreq_payload_create_from_x509(cacert);
|
|
||||||
request->add_payload(request, (payload_t*)certreq_payload);
|
request->add_payload(request, (payload_t*)certreq_payload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -421,10 +416,47 @@ static void build_notify(notify_type_t type, message_t *message, bool flush_mess
|
|||||||
message->add_payload(message, (payload_t*)notify);
|
message->add_payload(message, (payload_t*)notify);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Import certificate requests from a certreq payload
|
||||||
|
*/
|
||||||
|
static void import_certificate_request(certreq_payload_t *certreq_payload)
|
||||||
|
{
|
||||||
|
chunk_t keyids;
|
||||||
|
cert_encoding_t encoding = certreq_payload->get_cert_encoding(certreq_payload);
|
||||||
|
|
||||||
|
if (encoding != CERT_X509_SIGNATURE)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "certreq payload %N not supported, ignored",
|
||||||
|
cert_encoding_names, encoding);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyids = certreq_payload->get_data(certreq_payload);
|
||||||
|
|
||||||
|
while (keyids.len >= HASH_SIZE_SHA1)
|
||||||
|
{
|
||||||
|
chunk_t keyid = { keyids.ptr, HASH_SIZE_SHA1};
|
||||||
|
x509_t *cacert = charon->credentials->get_ca_certificate_by_keyid(charon->credentials, keyid);
|
||||||
|
|
||||||
|
if (cacert)
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "request for certificate issued by ca '%D'", cacert->get_subject(cacert));
|
||||||
|
DBG2(DBG_IKE, " with keyid %#B", &keyid);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
DBG1(DBG_IKE, "request for certificate issued by unknown ca");
|
||||||
|
DBG1(DBG_IKE, " with keyid %#B", &keyid);
|
||||||
|
}
|
||||||
|
keyids.ptr += HASH_SIZE_SHA1;
|
||||||
|
keyids.len -= HASH_SIZE_SHA1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Import a certificate from a cert payload
|
* Import a certificate from a cert payload
|
||||||
*/
|
*/
|
||||||
static void import_certificate(private_ike_auth_t *this, cert_payload_t *cert_payload)
|
static void import_certificate(cert_payload_t *cert_payload)
|
||||||
{
|
{
|
||||||
bool found;
|
bool found;
|
||||||
x509_t *cert;
|
x509_t *cert;
|
||||||
@@ -527,6 +559,7 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
|
|||||||
id_payload_t *idi_request = NULL;
|
id_payload_t *idi_request = NULL;
|
||||||
id_payload_t *idr_request = NULL;
|
id_payload_t *idr_request = NULL;
|
||||||
auth_payload_t *auth_request = NULL;
|
auth_payload_t *auth_request = NULL;
|
||||||
|
certreq_payload_t *certreq_request = NULL;
|
||||||
cert_payload_t *cert_request = NULL;
|
cert_payload_t *cert_request = NULL;
|
||||||
sa_payload_t *sa_request = NULL;
|
sa_payload_t *sa_request = NULL;
|
||||||
ts_payload_t *tsi_request = NULL;
|
ts_payload_t *tsi_request = NULL;
|
||||||
@@ -580,6 +613,9 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
|
|||||||
case AUTHENTICATION:
|
case AUTHENTICATION:
|
||||||
auth_request = (auth_payload_t*)payload;
|
auth_request = (auth_payload_t*)payload;
|
||||||
break;
|
break;
|
||||||
|
case CERTIFICATE_REQUEST:
|
||||||
|
certreq_request = (certreq_payload_t*)payload;
|
||||||
|
break;
|
||||||
case CERTIFICATE:
|
case CERTIFICATE:
|
||||||
cert_request = (cert_payload_t*)payload;
|
cert_request = (cert_payload_t*)payload;
|
||||||
break;
|
break;
|
||||||
@@ -699,9 +735,14 @@ static status_t get_response(private_ike_auth_t *this, message_t *request,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (certreq_request)
|
||||||
|
{ /* process certificate request payload */
|
||||||
|
import_certificate_request(certreq_request);
|
||||||
|
}
|
||||||
|
|
||||||
if (cert_request)
|
if (cert_request)
|
||||||
{ /* process certificate payload */
|
{ /* process certificate payload */
|
||||||
import_certificate(this, cert_request);
|
import_certificate(cert_request);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ /* process auth payload */
|
{ /* process auth payload */
|
||||||
@@ -923,7 +964,7 @@ static status_t conclude(private_ike_auth_t *this, message_t *response,
|
|||||||
|
|
||||||
if (cert_payload)
|
if (cert_payload)
|
||||||
{ /* process cert payload */
|
{ /* process cert payload */
|
||||||
import_certificate(this, cert_payload);
|
import_certificate(cert_payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
{ /* authenticate peer */
|
{ /* authenticate peer */
|
||||||
|
|||||||
Reference in New Issue
Block a user