Merge lp:~hipl-core/hipl/certificate-exchange into lp:hipl

Proposed by Diego Biurrun
Status: Superseded
Proposed branch: lp:~hipl-core/hipl/certificate-exchange
Merge into: lp:hipl
Diff against target: 3147 lines (+1398/-1002)
33 files modified
Makefile.am (+5/-1)
configure.ac (+2/-0)
doc/HOWTO.xml.in (+75/-0)
hipd/cert.c (+155/-81)
hipd/input.c (+0/-1)
hipd/output.c (+0/-1)
hipfw/cert.c (+167/-528)
hipfw/cert.h (+14/-24)
hipfw/conntrack.c (+20/-9)
hipfw/hipfw.c (+5/-7)
hipfw/hipfw.conf (+1/-0)
hipfw/hipfw_defines.h (+0/-1)
hipfw/main.c (+2/-1)
hipfw/pisa_cert.c (+0/-205)
hipfw/pisa_cert.h (+0/-47)
hipfw/rule_management.c (+23/-0)
hipfw/rule_management.h (+1/-0)
lib/core/builder.c (+12/-5)
lib/core/builder.h (+7/-9)
lib/core/cert.c (+286/-0)
lib/core/cert.h (+51/-0)
lib/core/certtools.c (+5/-5)
lib/core/conf.c (+132/-4)
lib/core/protodefs.h (+14/-0)
modules/cert/hipd/cert.c (+169/-49)
modules/cert/hipd/cert.h (+7/-20)
modules/cert/module_info.xml (+23/-0)
test/check_lib_core.c (+1/-0)
test/lib/core/cert.c (+189/-0)
test/lib/core/test_cert.pem (+15/-0)
test/lib/core/test_key.pem (+15/-0)
test/lib/core/test_suites.h (+1/-0)
tools/hipl_autobuild.sh (+1/-4)
To merge this branch: bzr merge lp:~hipl-core/hipl/certificate-exchange
Reviewer Review Type Date Requested Status
Miika Komu Approve
Review via email: mp+95634@code.launchpad.net

This proposal has been superseded by a proposal from 2012-03-09.

Description of the change

The certificate exchange branch is ready to be reviewed by the general public. Here is the short description from the HOWTO:

At the protocol level, HIPL implements the HIP_CERT parameter as defined in RFC 6253. Specifically, X509 certificates are supported, whereas no functionality is provided for SPKI certificates. HIP does not define the usage of certificates in the protocol exchange. In HIPL, we currently add certificates to the R2 in the BEX and the second update message U2 (e.g. during the mobility-triggered update exchange).

To post a comment you must log in.
Revision history for this message
Miika Komu (miika-iki) wrote :

Did I understand correctly, is the certificate parameter added only when the corresponding non-automatically generated file exists?

Can you remind why the PISA stuff was removed?

review: Needs Information
Revision history for this message
Miika Komu (miika-iki) wrote :

Forgot to mention:

Text conflict in hipd/cert.c
Text conflict in test/check_lib_core.c

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :

On Fri, Mar 02, 2012 at 10:23:21PM +0000, Miika Komu wrote:
> Review: Needs Information
>
> Can you remind why the PISA stuff was removed?

I'm not sure what you mean by PISA stuff here. We renamed everything
labeled PISA because it really is more generic functionality that can
be used outside of the PISA project.

Diego

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :

On Sat, Mar 03, 2012 at 07:15:22AM +0000, Miika Komu wrote:
> Forgot to mention:
>
> Text conflict in hipd/cert.c
> Text conflict in test/check_lib_core.c

Yes, I did not bother to merge the last two commits from trunk.
I can redo the merge request from a branch with latest trunk merged
tomorrow if that is preferred. But the conflicts should not make
much of a difference for reviewing.

Diego

Revision history for this message
Miika Komu (miika-iki) wrote :

Works for me.

review: Approve
Revision history for this message
René Hummen (rene-hummen) wrote :

The code to be merged has been tested and worked fine. Also the code looks ok. A few minor issues below.

On 02.03.2012, at 19:08, Diego Biurrun wrote:
> Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.

> === modified file 'hipfw/main.c'
> --- hipfw/main.c 2011-11-25 13:52:20 +0000
> +++ hipfw/main.c 2012-03-02 18:07:40 +0000
> @@ -37,14 +37,16 @@
>
> #include <stdio.h>
> #include <stdlib.h>
> +#include <string.h>
> #include <unistd.h>
> #include <sys/types.h>
>
> #include "lib/core/filemanip.h"
> #include "lib/core/debug.h"
> #include "lib/core/util.h"
> +#include "cert.h"
> +#include "conntrack.h"
> #include "hipfw.h"
> -#include "conntrack.h"
> #include "midauth.h"

Why was cert.h included here? -> Removed in new revision.

> === modified file 'modules/update/hipd/update.c'
> --- modules/update/hipd/update.c 2012-01-17 08:34:18 +0000
> +++ modules/update/hipd/update.c 2012-03-02 18:07:40 +0000
> @@ -57,6 +57,7 @@
> #include "lib/core/prefix.h"
> #include "lib/core/state.h"
> #include "lib/core/performance.h"
> +#include "modules/cert/hipd/cert.h"
> #include "update_builder.h"
> #include "update_locator.h"
> #include "update_param_handling.h"

Why was this include added? -> Removed in new revision.

--
Dipl.-Inform. Rene Hummen, Ph.D. Student
Chair of Communication and Distributed Systems
RWTH Aachen University, Germany
tel: +49 241 80 20772
web: http://www.comsys.rwth-aachen.de/team/rene-hummen/

6107. By René Hummen

remove unnecessary includes

6108. By René Hummen

add missing include

6109. By David Martin

Fix hipconf command parsing for 'acquire certificate'.

hipconf syntax was changed some time ago, so instead of
'hipconf acquire certificate <HIT>' it is
'hipconf daemon acquire certificate <HIT>'.

This commit makes hipconf correctly read the passed command again.
It does _not_ fix the segfault of hipd when it tries to actually
acquire the certificate.

6110. By David Martin

Cosmetics: uncrustify lib/core/conf.c.

6111. By Christoph Viethen

Fix three problem areas related to certificate creation:

Remove duplicate NCONF_free() in hipd/cert.c, fixing the segfault problem.

Fix lib/core/certtools.c:hip_open_conf() to correctly deallocate structures
pointed to by the "conf" handle in case of error. Also do away with a
redundant variable.

Repair lib/core/conf.c:conf_handle_certificate() and its interaction
with hip_do_hipconf(). The first function would generate a message,
and itself look after sending it to the hipd. Subsequently, the second
function mentioned would take the very same message and send it
again, causing havoc. Fix: Perform hip_msg_init() at the end of
the first function to indicate to hip_do_hipconf() that the message
has already been sent, just like some other "conf_handle_...()"
functions do it.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (18.6 KiB)

review needs-fixing

On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
>
> --- hipd/cert.c 2012-03-01 14:06:24 +0000
> +++ hipd/cert.c 2012-03-02 18:07:40 +0000

The functions in this file are HUUUUGE - IMO this needs some refactoring.

> @@ -682,89 +688,109 @@
> +
> + /* Were we sent a timestamp which indicates a requested cert validity? */
> + validity_param = hip_get_param(msg, HIP_PARAM_UINT);
> +
> + if (validity_param) {
> + const uint32_t valid_until_n = *(const uint32_t *) hip_get_param_contents_direct(validity_param);
> + const uint32_t valid_until_h = ntohl(valid_until_n);

Gah, pointer type punning.

> @@ -797,33 +821,67 @@
> +
> + X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
> + X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
> +
> + {
> + const time_t now = time(NULL);
> + time_t starttime = 0;
> + time_t endtime = 0;
> + time_t *starttime_p = NULL;
> + time_t *endtime_p = NULL;

The block braces are unnecessary, we allow mixed declarations and
statements.

> switch (algo) {
> case HIP_HI_RSA:
> - HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,
> + HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, (RSA *) ha->peer_pub_key), -1,
> "Failed to convert RSA to EVP_PKEY\n");
> HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
> "Failed to set public key of the certificate\n");
> break;
> case HIP_HI_DSA:
> - HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,
> + HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, (DSA *) ha->peer_pub_key), -1,
> "Failed to convert DSA to EVP_PKEY\n");

peer_pub_key is a void*, the casts are unnecessary.

> @@ -926,7 +984,25 @@
>
> + switch (host_id->rdata.algorithm) {
> + case HIP_HI_RSA:
> + HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, (RSA *) key), -1,
> + "Failed to convert RSA to EVP_PKEY\n");
> + break;
> + case HIP_HI_DSA:
> + HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, (DSA *) key), -1,
> + "Failed to convert DSA to EVP_PKEY\n");
> + break;

same here

> --- hipfw/pisa.c 2011-11-25 13:52:20 +0000
> +++ hipfw/cert.c 2012-03-02 18:07:40 +0000
> @@ -25,551 +25,192 @@
> +#include "rule_management.h"
> +#include "cert.h"
> +
> +// runtime configuration
> +int use_cert = false;

This could be static.

> +const char *root_certificate_file = NULL;

This is unused.

> --- lib/core/builder.c 2012-03-01 14:06:24 +0000
> +++ lib/core/builder.c 2012-03-02 18:07:40 +0000
> @@ -3388,16 +3395,21 @@
> int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, int len)
> {
> + int err = -1;
> + struct hip_cert_x509_resp subj = { 0 };
> +
> + if (len > 0 && (unsigned int) len <= sizeof(subj.der)) {
> + hip_set_param_type((struct hip_tlv_common *) &subj, HIP_PARAM_CERT_X509_REQ);
> + hip_calc_param_len((struct hip_tlv_common *) &subj,
> + sizeof(struct hip_cert...

6112. By Diego Biurrun

cert: Make variable not used outside of cert.c static.

6113. By Diego Biurrun

Remove unused root_certificate_file variable.

6114. By Diego Biurrun

Remove some unnecessary void* casts.

6115. By Diego Biurrun

Avoid some unnecessary pointer type punning.

6116. By Diego Biurrun

cosmetics: whitespace adjustments, drop unnecessary block braces, ordering

6117. By Diego Biurrun

Merge current tip of trunk.

6118. By Diego Biurrun

cosmetics: comment typos, prettyprinting, ordering

6119. By Diego Biurrun

Get rid of an unnecessary variable indirection in cert_DER_to_X509().

6120. By Diego Biurrun

builder: Make hip_build_param_cert_x509_{ver|resp} function parameter unsigned.

This is simpler than checking it is non-negative and casting.

6121. By Diego Biurrun

Merge two conditions in cert_match_public_key().

6122. By Diego Biurrun

Fix some Doxygen markup errors and wording improvements.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (6.9 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing

It still needs fixing, I'm just commenting on the issues I addressed.

> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
> > @@ -682,89 +688,109 @@
> > +
> > + /* Were we sent a timestamp which indicates a requested cert validity? */
> > + validity_param = hip_get_param(msg, HIP_PARAM_UINT);
> > +
> > + if (validity_param) {
> > + const uint32_t valid_until_n = *(const uint32_t *) hip_get_param_contents_direct(validity_param);
> > + const uint32_t valid_until_h = ntohl(valid_until_n);
>
> Gah, pointer type punning.

Fixed.

> > @@ -797,33 +821,67 @@
> > +
> > + X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
> > + X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
> > +
> > + {
> > + const time_t now = time(NULL);
> > + time_t starttime = 0;
> > + time_t endtime = 0;
> > + time_t *starttime_p = NULL;
> > + time_t *endtime_p = NULL;
>
> The block braces are unnecessary, we allow mixed declarations and
> statements.

Fixed.

Apparently Christoph's intention here was to reduce the scope of the
variables and possibly split the function into pieces along this line.
So if somebody wants to step forward and do that.. :)

> > switch (algo) {
> > case HIP_HI_RSA:
> > - HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,
> > + HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, (RSA *) ha->peer_pub_key), -1,
> > "Failed to convert RSA to EVP_PKEY\n");
> > HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
> > "Failed to set public key of the certificate\n");
> > break;
> > case HIP_HI_DSA:
> > - HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,
> > + HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, (DSA *) ha->peer_pub_key), -1,
> > "Failed to convert DSA to EVP_PKEY\n");
>
> peer_pub_key is a void*, the casts are unnecessary.

Fixed.

> > @@ -926,7 +984,25 @@
> >
> > + switch (host_id->rdata.algorithm) {
> > + case HIP_HI_RSA:
> > + HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, (RSA *) key), -1,
> > + "Failed to convert RSA to EVP_PKEY\n");
> > + break;
> > + case HIP_HI_DSA:
> > + HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, (DSA *) key), -1,
> > + "Failed to convert DSA to EVP_PKEY\n");
> > + break;
>
> same here

Fixed.

> > --- hipfw/pisa.c 2011-11-25 13:52:20 +0000
> > +++ hipfw/cert.c 2012-03-02 18:07:40 +0000
> > @@ -25,551 +25,192 @@
> > +#include "rule_management.h"
> > +#include "cert.h"
> > +
> > +// runtime configuration
> > +int use_cert = false;
>
> This could be static.

Fixed.

> > +const char *root_certificate_file = NULL;
>
> This is unused.

Fixed.

> > --- lib/core/builder.c 2012-03-01 14:06:24 +0000
> > +++ lib/core/builder.c 2012-03-02 18:07:40 +0000
> > @@ -3388,16 +3395,21 @@
> ...

Read more...

6123. By Diego Biurrun

Merge current trunk.

6124. By Diego Biurrun

Merge trunk again after landing of exponential backoff branch.

6125. By Diego Biurrun

Fix memory leaks in cert_match_public_key() and cert_verify_chain().

6126. By Diego Biurrun

Fix a number of memory leaks in the certificate unit test.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (4.9 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing
>
> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- test/lib/core/cert.c 1970-01-01 00:00:00 +0000
> > +++ test/lib/core/cert.c 2012-03-02 18:07:40 +0000
> > @@ -0,0 +1,189 @@
> > +
> > +START_TEST(test_cert_DER_encoding)
> > +{
> > + int len = 0;
> > + X509 *cert = NULL;
> > + X509 *cert_decoded = NULL;
> > + unsigned char *buf = NULL;
> > +
> > + HIP_DEBUG("Test DER en/decoding of X509 certificates.\n");
> > +
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len)) != NULL, NULL);
> > + fail_unless(X509_cmp(cert, cert_decoded) == 0, NULL);
> > +
> > + fail_unless((len = cert_X509_to_DER(NULL, &buf)) < 0, NULL);
> > + fail_unless((len = cert_X509_to_DER(cert, NULL)) < 0, NULL);
> > + fail_unless((len = cert_X509_to_DER(NULL, NULL)) < 0, NULL);
> > +
> > + fail_unless((cert_decoded = cert_DER_to_X509(NULL, len)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len - 1)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, len + 1)) == NULL, NULL);
> > + fail_unless((cert_decoded = cert_DER_to_X509(buf, 0)) == NULL, NULL);
> > +
> > + X509_free(cert);
> > + X509_free(cert_decoded);
>
> buf does not need to be freed?
>
> > +START_TEST(test_cert_match_public_key)
> > +{
> > + int err = 0;
> > + RSA *rsa = NULL;
> > + X509 *cert = NULL;
> > + EVP_PKEY *pkey = NULL;
> > +
> > + HIP_DEBUG("Test matching of public keys.\n");
> > +
> > + fail_unless((err = load_rsa_private_key(TEST_KEY, &rsa)) == 0, NULL);
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + pkey = EVP_PKEY_new();
> > + EVP_PKEY_assign_RSA(pkey, rsa);
> > + fail_unless((err = cert_match_public_key(cert, pkey)) == 1, NULL);
> > +
> > + fail_unless((err = cert_match_public_key(NULL, pkey)) == 0, NULL);
> > + fail_unless((err = cert_match_public_key(cert, NULL)) == 0, NULL);
> > + fail_unless((err = cert_match_public_key(NULL, NULL)) == 0, NULL);
> > +
> > + EVP_PKEY_free(pkey);
> > + X509_free(cert);
>
> RSA_free(rsa);
>
> .. at least if the doxy of load_rsa_private_key() is to be believed.
>
> > +START_TEST(test_cert_verify_chain)
> > +{
> > + int err = 0;
> > + X509 *cert = NULL;
> > + STACK_OF(X509) * chain = NULL;
> > +
> > + HIP_DEBUG("Test verification of certificate chains.\n");
> > +
> > + fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
> > + ENCODING_FORMAT_PEM)) != NULL,
> > + NULL);
> > + ...

Read more...

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (10.0 KiB)

On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> review needs-fixing

This branch still has serious issues, even after the number of fixes
I applied in the last few days. I'll ping the areas that I have
questions about and remain unfixed below.

> On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> >
> > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
>
> The functions in this file are HUUUUGE - IMO this needs some refactoring.

Any volunteers? The original authors maybe? I still don't really
understand the "big picture" of this branch.

> > --- lib/core/cert.c 1970-01-01 00:00:00 +0000
> > +++ lib/core/cert.c 2012-03-02 18:07:40 +0000
> > @@ -0,0 +1,292 @@
> > +/**
> > + * This function encodes the given certificate to its DER encoding for
> > + * transmission over the wire. The encoded certificate is written to @ *buf.
> > + *
> > + * @param cert the certificate to encode
> > + * @param buf the output is written here
> > + *
> > + * @return the length of the encoded data
> > + *
> > + * @note: The encoded data is in binary form and may contain embedded zeroes.
> > + * Functions such as strlen() will not return the correct length of the
> > + * encoded structure. Therefore length value returned by this function
> > + * should always be used.
> > + */
> > +int cert_X509_to_DER(X509 *const cert, unsigned char **buf)
> > +{
> > + int len;
> > +
> > + if (!cert) {
> > + HIP_ERROR("Cannot encode NULL-certificate\n");
> > + return -1;
> > + }
> > + if (!buf) {
> > + HIP_ERROR("Cannot create output buffer at NULL-pointer.\n");
> > + return -1;
> > + }
> > +
> > + *buf = NULL;
> > + len = i2d_X509(cert, buf);
> > +
> > + if (len < 0) {
> > + HIP_ERROR("Could not DER-encode the given certificate.\n");
> > + return -1;
> > + }
> > + return len;
> > +}
>
> The
>
> *buf = NULL;
>
> assignment looks suspicious to me, can somebody explain it?

Please somebody enlighten us.

> > +/**
> > + * Load a X509 certificate from @ file. If @ file contains more
> > + * than one certificate, the certificate at the top of the file is
> > + * returned.
> > + *
> > + * @param file the file to load the certficate from
> > + * @param fmt the input format of the certificate
> > + *
> > + * @return a X509 certificate on success, NULL on error
> > + */
> > +X509 *cert_load_x509_certificate(const char *const file,
> > + enum encoding_format fmt)
> > +{
> > + FILE *fp = NULL;
> > + X509 *cert = NULL;
> > +
> > + if (!file) {
> > + HIP_ERROR("Cannot read certificate from NULL-filename.\n");
> > + return NULL;
> > + }
> > +
> > + fp = fopen(file, "rb");
> > + if (!fp) {
> > + HIP_ERROR("Could not open file for reading: %s\n", file);
> > + return NULL;
> > + }
> > +
> > + if (fmt == ENCODING_FORMAT_PEM) {
> > + cert = PEM_read_X509(fp, NULL, NULL, NULL);
> > + } else if (fmt == ENCODING_FORMAT_DER...

6127. By Christoph Viethen

Fix a few more problems related to certificate generation:

Remove some redundancy from hipd/cert.c, and replace braces which served
to limit the scope of temporary variables.

Fix serious bug in lib/core/builder.c:build_param_cert_x509, which caused
corrupt certificate length value to be transmitted on little-endian
platforms. Also add the zeroing of the entire packet (again), to ease
debugging. Additionally, re-add the check for sufficient target space
before performing memcpy().

Fix function cert_match_public_key(), enabling it to cope with OpenSSL's
"creative" error handling and return codes (verified against OpenSSL
0.9.8 source code).

Revision history for this message
Miika Komu (miika-iki) wrote :

Hi,

On 03/12/2012 10:29 PM, Diego Biurrun wrote:
>> > On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
>>> > > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
>>> > >
>>> > > --- hipd/cert.c 2012-03-01 14:06:24 +0000
>>> > > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
>> >
>> > The functions in this file are HUUUUGE - IMO this needs some refactoring.
> Any volunteers? The original authors maybe? I still don't really
> understand the "big picture" of this branch.

not volunteering, but asking if the merge make things worse or keep them
function length the same? If the length is the same, this should be
handled separately.

Revision history for this message
Diego Biurrun (diego-biurrun) wrote :
Download full text (6.3 KiB)

On Mon, Mar 12, 2012 at 09:29:29PM +0100, Diego Biurrun wrote:
> On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
> > On Fri, Mar 02, 2012 at 06:08:20PM +0000, Diego Biurrun wrote:
> > > Diego Biurrun has proposed merging lp:~hipl-core/hipl/certificate-exchange into lp:hipl.
> > >
> > > --- hipd/cert.c 2012-03-01 14:06:24 +0000
> > > +++ hipd/cert.c 2012-03-02 18:07:40 +0000
> >
> > The functions in this file are HUUUUGE - IMO this needs some refactoring.
>
> Any volunteers? The original authors maybe? I still don't really
> understand the "big picture" of this branch.

Left for never^wlater.

> > > --- lib/core/cert.c 1970-01-01 00:00:00 +0000
> > > +++ lib/core/cert.c 2012-03-02 18:07:40 +0000
> > > @@ -0,0 +1,292 @@
> > > +/**
> > > + * Load a X509 certificate from @ file. If @ file contains more
> > > + * than one certificate, the certificate at the top of the file is
> > > + * returned.
> > > + *
> > > + * @param file the file to load the certficate from
> > > + * @param fmt the input format of the certificate
> > > + *
> > > + * @return a X509 certificate on success, NULL on error
> > > + */
> > > +X509 *cert_load_x509_certificate(const char *const file,
> > > + enum encoding_format fmt)
> > > +{
> > > + FILE *fp = NULL;
> > > + X509 *cert = NULL;
> > > +
> > > + if (!file) {
> > > + HIP_ERROR("Cannot read certificate from NULL-filename.\n");
> > > + return NULL;
> > > + }
> > > +
> > > + fp = fopen(file, "rb");
> > > + if (!fp) {
> > > + HIP_ERROR("Could not open file for reading: %s\n", file);
> > > + return NULL;
> > > + }
> > > +
> > > + if (fmt == ENCODING_FORMAT_PEM) {
> > > + cert = PEM_read_X509(fp, NULL, NULL, NULL);
> > > + } else if (fmt == ENCODING_FORMAT_DER) {
> > > + cert = d2i_X509_fp(fp, NULL);
> > > + } else {
> > > + HIP_ERROR("Invalid encoding format %i \n", fmt);
> > > + return NULL;
> > > + }
> >
> > switch/case? Might more formats get added here?
>
> Anybody?

Converted to switch/case, looks nicer at least.

> > > + if (fclose(fp)) {
> > > + HIP_ERROR("Error closing file: %s\n", file);
> > > + X509_free(cert);
> > > + return NULL;
> > > + } else if (!cert) {
> > > + HIP_ERROR("Could not decode certificate from file.\n");
> > > + return NULL;
> > > + }
> > > +
> > > + return cert;
> > > +}
> >
> > If I read this correctly, fp will not get closed on encountering an
> > invalid encoding format.
>
> Is my assessment correct?

It is correct, function logic fixed on branch.

> > > +/**
> > > + * Search for hip_cert parameter in @ msg and try to decode the data in
> > > + * the first certificate parameter of a X509 certificate.
> > > + *
> > > + * @param msg the message to extract the certificate from
> > > + *
> > > + * @return the first X509 certificate found in the message on success,
> > > + * NULL on error and if no certificates were found
> > > + */
> > > +X509 *cert_get_X509_from_msg(const struct hip_common *const msg)
> > > +{
> > > + const struct hip_cert *param_cert = NULL;
> > > +
> > > + ...

Read more...

6128. By Diego Biurrun

Merge current trunk.

6129. By Diego Biurrun

Fix program logic in cert_load_x509_certificate().

The function would not correctly close file descriptors on error.

6130. By Diego Biurrun

Fix another memleak in the test_cert_DER_encoding() unit test.

Revision history for this message
Christof Mroz (christof-mroz) wrote :

On 13.03.2012 17:31, Diego Biurrun wrote:
> On Mon, Mar 12, 2012 at 09:29:29PM +0100, Diego Biurrun wrote:
>> On Thu, Mar 08, 2012 at 06:41:47PM +0100, Diego Biurrun wrote:
>>> What is "param_cert + 1" supposed to be? Are you trying to move the
>>> pointer past the struct? This is extremely brittle, see the cast
>>> and the length calculation that are necessary.
>>
>> I'm still mystified about this one.
>
> Christoph confirms the intention. Repairing this likely entails quite
> a bit of fiddling with structures.

Related:
https://answers.launchpad.net/hipl/+question/151048

>>>> + if (optc == 2&& is_pos_natural_number(opt[1])) {
>>>
>>> OK, what exactly is the problem here? Why do you need the utility function?
>>
>> Can the original author shed some light on this?
>
> Christoph said scanf did not work for him. I guess we'll trust his word.

I still consider explicit type checks an anti pattern which should be
replaced by coercion, in this case scanf(), whenever easily possible.

As a fan of obscure facts I'd really like to know why scanf("%u",...)
failed. Don't let my curiosity stall the merge, though.

6131. By René Hummen

add missing type in cert enum

This fixes an issue where the hipd would send certificates with the
type RESERVED (0) by default, instead of the correct type.

6132. By René Hummen

merge trunk revision 6332

6133. By Christoph Viethen

Fix defective logic in conf_handle_certificate().

Still an awfully long function, though.

6134. By Christoph Viethen

Refactor conf_handle_certificate(), moving the functionality that evaluates
the input parameters and converts them into HIP message parameters into a
separate function conf_handle_certificate_parms().

Also, overhaul the comments: Make sure they line-break before 80 chars,
clarify / shorten some of them, and add Doxygen headers.

6135. By Christoph Viethen

Fix minor off-by-one bug in lib/core/builder.c:build_param_cert_x509().

Also, replace one occurence of "struct in6_addr" by "hip_hit_t". Finally,
fix a little typo in a comment.

6136. By Christoph Viethen

Correct type of the "der_len" element of the hip_cert_x509_resp structure
(see lib/core/protodefs.h) to be uint32_t. This structure reflects the
format of HIP messages on the wire, so the typical rules (use network
byte order, define sizes of struct elements unambiguously ... ) apply.

This change causes a number of other changes in places where the very
same value gets handled. Note also that htonl() and ntohl() already were
used in a few of these places for byte order conversion of said value;
they generally use uint32_t for their input and output, so using
different types instead was just asking for trouble.

Unmerged revisions

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'Makefile.am'
--- Makefile.am 2012-03-01 14:06:24 +0000
+++ Makefile.am 2012-03-09 12:45:28 +0000
@@ -31,10 +31,10 @@
31EXTRA_DIST += .vimrc process_modules.py version.h31EXTRA_DIST += .vimrc process_modules.py version.h
32EXTRA_DIST += debian doc patches packaging tools/bazaar tools/maintainer32EXTRA_DIST += debian doc patches packaging tools/bazaar tools/maintainer
33EXTRA_DIST += $(wildcard modules/*/module_info.xml)33EXTRA_DIST += $(wildcard modules/*/module_info.xml)
34EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/test/lib/core/,*.pem))
34EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/tools/,*.cfg *.pl *.sh *.xml))35EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/tools/,*.cfg *.pl *.sh *.xml))
35EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/hipfw/,*.cfg))36EXTRA_DIST += $(wildcard $(addprefix $(srcdir)/hipfw/,*.cfg))
36EXTRA_DIST += $(HIPL_HEADER_LIST)37EXTRA_DIST += $(HIPL_HEADER_LIST)
37EXTRA_DIST += hipd/pisa.c hipfw/pisa.c hipfw/pisa_cert.c
3838
39### user programs ###39### user programs ###
40bin_PROGRAMS = test/auth_performance \40bin_PROGRAMS = test/auth_performance \
@@ -122,6 +122,7 @@
122 hipd/user_ipsec_sadb_api.c \122 hipd/user_ipsec_sadb_api.c \
123 modules/heartbeat/hipd/heartbeat.c \123 modules/heartbeat/hipd/heartbeat.c \
124 modules/heartbeat_update/hipd/hb_update.c \124 modules/heartbeat_update/hipd/hb_update.c \
125 modules/cert/hipd/cert.c \
125 modules/update/hipd/update.c \126 modules/update/hipd/update.c \
126 modules/update/hipd/update_builder.c \127 modules/update/hipd/update_builder.c \
127 modules/update/hipd/update_locator.c \128 modules/update/hipd/update_locator.c \
@@ -139,6 +140,7 @@
139 tools/nsupdate/nsupdate.conf140 tools/nsupdate/nsupdate.conf
140141
141hipfw_hipfw_sources = hipfw/cache.c \142hipfw_hipfw_sources = hipfw/cache.c \
143 hipfw/cert.c \
142 hipfw/dlist.c \144 hipfw/dlist.c \
143 hipfw/esp_prot_api.c \145 hipfw/esp_prot_api.c \
144 hipfw/esp_prot_config.c \146 hipfw/esp_prot_config.c \
@@ -170,6 +172,7 @@
170172
171lib_core_libhipcore_la_SOURCES = lib/core/builder.c \173lib_core_libhipcore_la_SOURCES = lib/core/builder.c \
172 lib/core/capability.c \174 lib/core/capability.c \
175 lib/core/cert.c \
173 lib/core/certtools.c \176 lib/core/certtools.c \
174 lib/core/conf.c \177 lib/core/conf.c \
175 lib/core/crypto.c \178 lib/core/crypto.c \
@@ -220,6 +223,7 @@
220 $(hipfw_hipfw_sources)223 $(hipfw_hipfw_sources)
221224
222test_check_lib_core_SOURCES = test/check_lib_core.c \225test_check_lib_core_SOURCES = test/check_lib_core.c \
226 test/lib/core/cert.c \
223 test/lib/core/crypto.c \227 test/lib/core/crypto.c \
224 test/lib/core/hit.c \228 test/lib/core/hit.c \
225 test/lib/core/hostid.c \229 test/lib/core/hostid.c \
226230
=== modified file 'configure.ac'
--- configure.ac 2012-03-08 14:36:01 +0000
+++ configure.ac 2012-03-09 12:45:28 +0000
@@ -101,6 +101,8 @@
101AC_DEFINE_UNQUOTED(HIPL_LOCKDIR, "$(eval echo $lockdir)")101AC_DEFINE_UNQUOTED(HIPL_LOCKDIR, "$(eval echo $lockdir)")
102AH_TEMPLATE(HIPL_LOCKDIR, [default lock file location])102AH_TEMPLATE(HIPL_LOCKDIR, [default lock file location])
103103
104AC_DEFINE_UNQUOTED(HIPL_SOURCEDIR, "$(eval echo $srcdir)")
105AH_TEMPLATE(HIPL_SOURCEDIR, [HIPL source directory location])
104# Make sure that pythondir does not contain ${prefix} or similar so that it106# Make sure that pythondir does not contain ${prefix} or similar so that it
105# can be substituted into our Python scripts.107# can be substituted into our Python scripts.
106AC_SUBST(pythondir, $(eval echo $pythondir))108AC_SUBST(pythondir, $(eval echo $pythondir))
107109
=== modified file 'doc/HOWTO.xml.in'
--- doc/HOWTO.xml.in 2012-01-25 10:44:48 +0000
+++ doc/HOWTO.xml.in 2012-03-09 12:45:28 +0000
@@ -2532,6 +2532,81 @@
25322532
2533 </chapter>2533 </chapter>
25342534
2535<chapter id="ch_cert_exchange">
2536 <title>Certificate Exchange</title>
2537
2538 <section id="ch_cert_functionality">
2539 <title>Provided functionality</title>
2540 <para>At the protocol level, HIPL implements the HIP_CERT parameter as
2541 defined in RFC 6253. Specifically, X509 certificates are supported, whereas
2542 no functionality is provided for SPKI certificates. HIP does not define
2543 the usage of certificates in the protocol exchange. In HIPL, we currently
2544 add certificates to the R2 in the BEX and the second update message U2
2545 (e.g. during the mobility-triggered update exchange). The HIP firewall
2546 verifies the certificate in the R2 and U2 if configured accordingly. If your
2547 use case requires certificates to be included in different messages, changes
2548 in the source code will be necessary.</para>
2549 </section>
2550
2551 <section id="ch_cert_usage">
2552 <title>Setting up a network scenario with certificates</title>
2553 <para>For the following guide, we assume a setup consisting of three
2554 machines (A, B, and C), where B is situated on the forwarding path between
2555 A and C. A and C execute the hipd, while B executes the hipfw. The hipd
2556 automatically adds a certificate to R2s and U2s if a file called
2557 host-cert.der is located in @sysconfdir@. The hipfw checks for certificates
2558 if certificate-based rules exist in @sysconfdir@/hipfw.conf.</para>
2559 <para>To set up certificates, you have to perform the following steps:</para>
2560 <itemizedlist>
2561 <listitem><para>Generate a root certificate in PEM format (e.g. with
2562 OpenSSL).</para></listitem>
2563 <listitem><para>Copy the root certificate to @sysconfdir@/ca-root-cert.pem on
2564 B.</para></listitem>
2565 <listitem><para>Add a certificate-based rule to @sysconfdir@/hipfw.conf on B
2566 (e.g. 'FORWARD -cert @sysconfdir@/ca-root-cert.pem ACCEPT').</para>
2567 </listitem>
2568 <listitem><para>Generate a certificate in DER format for the HI used by C
2569 and place it at @sysconfdir@/host-cert.der on C.</para></listitem>
2570 <listitem><para>No changes are required for A if its role is restricted to
2571 an initiator. Otherwise, A requires the same setup as C.</para></listitem>
2572 </itemizedlist>
2573 <para>The setup of a certificate-based network scenario can be vastly
2574 simplified by using a fourth HIPL-enabled host D as the certificate
2575 authority. In this case, generate the root certificate on D by running:
2576 </para>
2577 <para><programlisting>
2578 openssl req -new -x509 -key @sysconfdir@/hip_host_rsa_key_pub -out ca-root-cert.pem
2579 </programlisting></para>
2580 <para>NOTE: Apart from the common name, all fields in the certificate can be
2581 empty. The common name must contain the HIT of D.</para>
2582 <para>Now, run a BEX between C and D. After the BEX has succeeded, run the
2583 following command on D as root in order to generate the certificate for C:
2584 </para>
2585 <para><programlisting>
2586 hipconf acquire certificate #HIT_OF_C# > host-cert.der
2587 </programlisting></para>
2588 <para>As the final step, copy the certificates to the places mentioned in
2589 the guide above.</para>
2590 </section>
2591
2592 <section id="ch_cert_troubleshooting">
2593 <title>Troubleshooting</title>
2594 <para>There are a couple of things that may go wrong in a certificate-based
2595 setup. The most common ones are listed below. Please, make sure to check
2596 the listed items before asking questions on the hipl-users mailing list.</para>
2597 <itemizedlist>
2598 <listitem><para>Ensure that the certificates have not yet expired (e.g.
2599 by checking the certificate lifetime with OpenSSL).</para></listitem>
2600 <listitem><para>Validate that the time is set correctly on all hosts.
2601 </para></listitem>
2602 <listitem><para>Verify the certificate chain consisting of
2603 root-ca-cert.pem and host-cert.der with an external tool (e.g. with
2604 OpenSSL).</para></listitem>
2605 </itemizedlist>
2606 </section>
2607
2608</chapter> <!-- ch_cert_exchange -->
2609
2535<chapter id="ch_exp_extensions">2610<chapter id="ch_exp_extensions">
2536 <title>Other Experimental HIP Extensions</title>2611 <title>Other Experimental HIP Extensions</title>
25372612
25382613
=== modified file 'hipd/cert.c'
--- hipd/cert.c 2012-03-01 14:06:24 +0000
+++ hipd/cert.c 2012-03-09 12:45:28 +0000
@@ -49,10 +49,13 @@
49#include "lib/core/common.h"49#include "lib/core/common.h"
50#include "lib/core/crypto.h"50#include "lib/core/crypto.h"
51#include "lib/core/debug.h"51#include "lib/core/debug.h"
52#include "lib/core/hit.h"
52#include "lib/core/ife.h"53#include "lib/core/ife.h"
54#include "lib/core/prefix.h"
53#include "lib/core/protodefs.h"55#include "lib/core/protodefs.h"
54#include "lib/core/straddr.h"56#include "lib/core/straddr.h"
55#include "lib/core/gpl/pk.h"57#include "lib/core/gpl/pk.h"
58#include "hadb.h"
56#include "hidb.h"59#include "hidb.h"
57#include "cert.h"60#include "cert.h"
5861
@@ -661,20 +664,19 @@
661 */664 */
662int hip_cert_x509v3_handle_request_to_sign(struct hip_common *msg)665int hip_cert_x509v3_handle_request_to_sign(struct hip_common *msg)
663{666{
664 int err = 0, i = 0, nid = 0, ret = 0, secs = 0, algo = 0;667 int err = 0, i = 0, ret = 0, secs = 0, algo = 0;
665 CONF *conf;668 CONF *conf = NULL;
666 CONF_VALUE *item;669 CONF_VALUE *item;
667 STACK_OF(CONF_VALUE) *sec_general = NULL;670 STACK_OF(CONF_VALUE) *sec_general = NULL;
668 STACK_OF(CONF_VALUE) *sec_name = NULL;
669 STACK_OF(CONF_VALUE) *sec_ext = NULL;671 STACK_OF(CONF_VALUE) *sec_ext = NULL;
670672
671 X509_REQ *req = NULL;
672 X509_NAME *issuer = NULL;673 X509_NAME *issuer = NULL;
673 X509_NAME *subj = NULL;674 X509_NAME *subj = NULL;
674 X509_EXTENSION *ext = NULL;675 X509_EXTENSION *ext = NULL;
675 STACK_OF(X509_EXTENSION) *extlist = NULL;676 STACK_OF(X509_EXTENSION) *extlist = NULL;
676 X509_NAME_ENTRY *ent;677 X509_NAME_ENTRY *ent = NULL;
677 EVP_PKEY *pkey;678 EVP_PKEY *pkey = NULL;
679 EVP_PKEY *sig_key = NULL;
678 /** XX TODO THIS should come from a configuration file680 /** XX TODO THIS should come from a configuration file
679 * monotonically increasing counter */681 * monotonically increasing counter */
680 long serial = 0;682 long serial = 0;
@@ -682,89 +684,108 @@
682 X509 *cert;684 X509 *cert;
683 X509V3_CTX ctx;685 X509V3_CTX ctx;
684 const struct hip_cert_x509_req *subject;686 const struct hip_cert_x509_req *subject;
685 char subject_hit[41];687 char subject_hit[INET6_ADDRSTRLEN];
686 char issuer_hit[41];688 char issuer_hit[INET6_ADDRSTRLEN] = { 0 };
687 char ialtname[45];689 char ialtname[INET6_ADDRSTRLEN + 3];
688 char saltname[45];690 char saltname[INET6_ADDRSTRLEN + 3];
689 struct in6_addr *issuer_hit_n;691 hip_hit_t *issuer_hit_n = NULL;
690 struct hip_host_id *host_id;692 struct hip_host_id *host_id = NULL;
691 RSA *rsa = NULL;693 void *key = NULL;
692 DSA *dsa = NULL;
693 unsigned char *der_cert = NULL;694 unsigned char *der_cert = NULL;
694 int der_cert_len = 0;695 int der_cert_len = 0;
695 char arg1[21];696 char arg1[21];
696 char arg2[21];697 char arg2[21];
697698 const struct hip_tlv_common *validity_param = NULL;
698 HIP_IFEL(!(issuer_hit_n = malloc(sizeof(struct in6_addr))), -1,699 time_t expiry_time = 0;
700 const struct hip_hadb_state *ha = NULL;
701
702
703 HIP_IFEL(!(issuer_hit_n = malloc(sizeof(hip_hit_t))), -1,
699 "Malloc for subject failed\n");704 "Malloc for subject failed\n");
700 HIP_IFEL(!(pkey = malloc(sizeof(EVP_PKEY))), -1,705 HIP_IFEL(!(pkey = EVP_PKEY_new()), -1,
701 "Malloc for pkey failed\n");706 "Allocating subject pub key failed\n");
707 HIP_IFEL(!(sig_key = EVP_PKEY_new()), -1,
708 "Allocating issuer signature key failed\n");
702709
703 OpenSSL_add_all_algorithms();
704 ERR_load_crypto_strings();710 ERR_load_crypto_strings();
705711
706 HIP_DEBUG("Reading configuration file (%s)\n", HIP_CERT_CONF_PATH);712 HIP_DEBUG("Reading configuration file (%s)\n", HIP_CERT_CONF_PATH);
707 conf = hip_open_conf(HIP_CERT_CONF_PATH);713 conf = hip_open_conf(HIP_CERT_CONF_PATH);
708 sec_general = hip_read_conf_section("hip_x509v3", conf);714 sec_general = hip_read_conf_section("hip_x509v3", conf);
709 sec_name = hip_read_conf_section("hip_x509v3_name", conf);
710 sec_ext = hip_read_conf_section("hip_x509v3_extensions", conf);715 sec_ext = hip_read_conf_section("hip_x509v3_extensions", conf);
711 NCONF_free(conf);
712716
713 /* Get the general information */717 /* Fail if the hip_x509v3 or hip_x509v3_name sections are not found. */
714 HIP_IFEL(sec_general == NULL, -1,718 HIP_IFEL(sec_general == NULL, -1,
715 "Failed to load general certificate information\n");719 "Failed to load general certificate information\n");
716 HIP_IFEL(!(req = X509_REQ_new()), -1, "Failed to create X509_REQ object");
717
718 HIP_IFEL(sec_name == NULL, -1,
719 "Failed to load issuer naming information for the certificate\n");
720720
721 /* Issuer naming */721 /* Issuer naming */
722 if (sec_general != NULL) {722 /* Loop through the conf stack for general information */
723 /* Loop through the conf stack for general information */723 for (i = 0; i < sk_CONF_VALUE_num(sec_general); i++) {
724 extlist = sk_X509_EXTENSION_new_null();724 item = sk_CONF_VALUE_value(sec_general, i);
725 for (i = 0; i < sk_CONF_VALUE_num(sec_general); i++) {725 if (!strcmp(item->name, "issuerhit")) {
726 item = sk_CONF_VALUE_value(sec_general, i);726 ret = inet_pton(AF_INET6, item->value, issuer_hit_n);
727 if (!strcmp(item->name, "issuerhit")) {727 HIP_IFEL(ret != 1, -1,
728 strcpy(issuer_hit, item->value);728 "Failed to convert issuer HIT to hip_hit_t\n");
729 ret = inet_pton(AF_INET6, item->value, issuer_hit_n);729 HIP_DEBUG_HIT("Issuer HIT", issuer_hit_n);
730 HIP_IFEL(ret < 0 && errno == EAFNOSUPPORT, -1,730 hip_convert_hit_to_str(issuer_hit_n, NULL, issuer_hit);
731 "Failed to convert issuer HIT to hip_hit_t\n");731 }
732 HIP_DEBUG_HIT("Issuer HIT", issuer_hit_n);732 if (!strcmp(item->name, "days")) {
733 HIP_IFEL(!inet_ntop(AF_INET6, issuer_hit_n,733 secs = HIP_CERT_DAY * atoi(item->value);
734 issuer_hit, sizeof(issuer_hit)),734 }
735 -1, "Failed to convert subject hit to "735 }
736 "presentation format\n");736
737 }737 /* In case no issuerhit was in the config, just use our default HIT. */
738 if (!strcmp(item->name, "days")) {738 if (issuer_hit[0] == 0) {
739 secs = HIP_CERT_DAY * atoi(item->value);739 HIP_IFEL(hip_get_default_hit(issuer_hit_n), -1,
740 }740 "Unable to determine default HIT\n");
741 }741 hip_convert_hit_to_str(issuer_hit_n, NULL, issuer_hit);
742 }742 }
743 HIP_IFEL(!(issuer = X509_NAME_new()), -1, "Failed to set create issuer name");743
744 nid = OBJ_txt2nid("commonName");744 HIP_IFEL(!(issuer = X509_NAME_new()), -1, "Failed to create issuer name");
745 HIP_IFEL(nid == NID_undef, -1, "NID text not defined\n");745
746 HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,746 HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, MBSTRING_ASC,
747 (unsigned char *) issuer_hit, -1)), -1,747 (unsigned char *) issuer_hit, -1)), -1,
748 "Failed to create name entry for issuer\n");748 "Failed to create name entry for issuer\n");
749 HIP_IFEL(X509_NAME_add_entry(issuer, ent, -1, 0) != 1, -1,749 HIP_IFEL(X509_NAME_add_entry(issuer, ent, -1, 0) != 1, -1,
750 "Failed to add entry to issuer name\n");750 "Failed to add entry to issuer name\n");
751751
752 X509_NAME_ENTRY_free(ent); /* "ent" var will be re-used */
753 ent = NULL;
754
752 /* Subject naming */755 /* Subject naming */
753 /* Get the subject hit from msg */756 /* Get the subject hit from msg */
754 HIP_IFEL(!(subject = hip_get_param(msg, HIP_PARAM_CERT_X509_REQ)),757 HIP_IFEL(!(subject = hip_get_param(msg, HIP_PARAM_CERT_X509_REQ)),
755 -1, "No cert_info struct found\n");758 -1, "No cert_x509_req struct found\n");
756 HIP_IFEL(!inet_ntop(AF_INET6, &subject->addr, subject_hit, sizeof(subject_hit)),759 HIP_IFEL(!ipv6_addr_is_hit(&subject->addr),
757 -1, "Failed to convert subject hit to presentation format\n");760 -1, "Address in certificate request is no HIT.\n");
758 HIP_IFEL(!(subj = X509_NAME_new()), -1, "Failed to set create subject name");761 HIP_DEBUG_HIT("Subject HIT", &subject->addr);
759 nid = OBJ_txt2nid("commonName");762 hip_convert_hit_to_str(&subject->addr, NULL, subject_hit);
760 HIP_IFEL(nid == NID_undef, -1, "NID text not defined\n");763
761 HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, nid, MBSTRING_ASC,764 HIP_IFEL(!(subj = X509_NAME_new()), -1, "Failed to create subject name");
765
766 HIP_IFEL(!(ent = X509_NAME_ENTRY_create_by_NID(NULL, NID_commonName, MBSTRING_ASC,
762 (unsigned char *) subject_hit, -1)), -1,767 (unsigned char *) subject_hit, -1)), -1,
763 "Failed to create name entry for subject\n");768 "Failed to create name entry for subject\n");
764 HIP_IFEL(X509_NAME_add_entry(subj, ent, -1, 0) != 1, -1,769 HIP_IFEL(X509_NAME_add_entry(subj, ent, -1, 0) != 1, -1,
765 "Failed to add entry to subject name\n");770 "Failed to add entry to subject name\n");
766 HIP_IFEL(X509_REQ_set_subject_name(req, subj) != 1, -1,771
767 "Failed to add subject name to certificate request\n");772 /* Were we sent a timestamp which indicates a requested cert validity? */
773 validity_param = hip_get_param(msg, HIP_PARAM_UINT);
774
775 if (validity_param) {
776 const uint32_t *valid_until_n = hip_get_param_contents_direct(validity_param);
777 const uint32_t valid_until_h = ntohl(*valid_until_n);
778
779 /* If time_t is only 32 bits wide and signed, we cannot copy a value of
780 * valid_until_h which has its MSB set since it would be misunderstood
781 * as being negative; so only set the value if this is not the case. */
782 if (!(sizeof(time_t) == 4 && ((time_t) -1 < 0) &&
783 (0x80000000 & valid_until_h))) {
784 expiry_time = valid_until_h;
785 } else {
786 HIP_OUT_ERR(-1, "Received invalid timestamp parameter.\n");
787 }
788 }
768789
769 /* XX TODO add a check to skip subjectAltName and issuerAltName because they are790 /* XX TODO add a check to skip subjectAltName and issuerAltName because they are
770 * already in use by with IP:<hit> stuff */791 * already in use by with IP:<hit> stuff */
@@ -778,8 +799,6 @@
778 "Failed to create extension\n");799 "Failed to create extension\n");
779 sk_X509_EXTENSION_push(extlist, ext);800 sk_X509_EXTENSION_push(extlist, ext);
780 }801 }
781 HIP_IFEL(!X509_REQ_add_extensions(req, extlist), -1,
782 "Failed to add extensions to the request\n");
783 }802 }
784803
785 /** NOW WE ARE READY TO CREATE A CERTIFICATE FROM THE REQUEST */804 /** NOW WE ARE READY TO CREATE A CERTIFICATE FROM THE REQUEST */
@@ -797,33 +816,63 @@
797 "Failed to set subject name of certificate\n");816 "Failed to set subject name of certificate\n");
798 HIP_IFEL(X509_set_issuer_name(cert, issuer) != 1, -1,817 HIP_IFEL(X509_set_issuer_name(cert, issuer) != 1, -1,
799 "Failed to set issuer name of certificate\n");818 "Failed to set issuer name of certificate\n");
800 HIP_IFEL(!X509_gmtime_adj(X509_get_notBefore(cert), 0), -1,819
820 X509_get_notBefore(cert)->type = V_ASN1_GENERALIZEDTIME;
821 X509_get_notAfter(cert)->type = V_ASN1_GENERALIZEDTIME;
822
823 const time_t now = time(NULL);
824 time_t starttime = 0, endtime = 0;
825 time_t *starttime_p = NULL, *endtime_p = NULL;
826
827 if (expiry_time) {
828 /* A specific expiry time is demanded by the caller. */
829 if (now < expiry_time) {
830 /* Just set it up as wanted. */
831 starttime = now;
832 endtime = expiry_time;
833 } else {
834 /* Just set the start time to one second before the expiry time.
835 * This yields a - syntactically - valid certificate. It is not
836 * our task to second-guess the motives for requesting an expiry
837 * time from the past. */
838 if (expiry_time == 1) {
839 expiry_time++; /* another pathological case */
840 }
841 starttime = expiry_time - 1;
842 endtime = expiry_time;
843 }
844
845 starttime_p = &starttime;
846 endtime_p = &endtime;
847 secs = 0;
848 } else {
849 starttime_p = NULL;
850 endtime_p = NULL;
851 if (secs <= 0) {
852 secs = 10; /* and yet another one */
853 }
854 }
855
856 HIP_IFEL(!X509_time_adj(X509_get_notBefore(cert), 0, starttime_p), -1,
801 "Error setting beginning time of the certificate");857 "Error setting beginning time of the certificate");
802 HIP_IFEL(!X509_gmtime_adj(X509_get_notAfter(cert), secs), -1,858 HIP_IFEL(!X509_time_adj(X509_get_notAfter(cert), secs, endtime_p), -1,
803 "Error setting ending time of the certificate");859 "Error setting ending time of the certificate");
804860
805 HIP_DEBUG("Getting the key\n");861 /* Get the subject public key from HADB */
806862 HIP_IFEL(!(ha = hip_hadb_find_byhits(issuer_hit_n, &subject->addr)),
807 HIP_IFEL(hip_get_host_id_and_priv_key(issuer_hit_n,863 -1, "Could not retrieve host association for subject HIT\n");
808 HIP_ANY_ALGO,864
809 &host_id,865 algo = ha->peer_pub->rdata.algorithm;
810 (void *) &rsa),
811 -1, "Private key not found\n");
812
813 algo = host_id->rdata.algorithm;
814 if (algo == HIP_HI_DSA) {
815 dsa = (DSA *) rsa;
816 }
817866
818 switch (algo) {867 switch (algo) {
819 case HIP_HI_RSA:868 case HIP_HI_RSA:
820 HIP_IFEL(!EVP_PKEY_assign_RSA(pkey, rsa), -1,869 HIP_IFEL(!EVP_PKEY_set1_RSA(pkey, ha->peer_pub_key), -1,
821 "Failed to convert RSA to EVP_PKEY\n");870 "Failed to convert RSA to EVP_PKEY\n");
822 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,871 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
823 "Failed to set public key of the certificate\n");872 "Failed to set public key of the certificate\n");
824 break;873 break;
825 case HIP_HI_DSA:874 case HIP_HI_DSA:
826 HIP_IFEL(!EVP_PKEY_assign_DSA(pkey, dsa), -1,875 HIP_IFEL(!EVP_PKEY_set1_DSA(pkey, ha->peer_pub_key), -1,
827 "Failed to convert DSA to EVP_PKEY\n");876 "Failed to convert DSA to EVP_PKEY\n");
828 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,877 HIP_IFEL(X509_set_pubkey(cert, pkey) != 1, -1,
829 "Failed to set public key of the certificate\n");878 "Failed to set public key of the certificate\n");
@@ -926,7 +975,25 @@
926 HIP_OUT_ERR(-1, "Unknown algorithm\n");975 HIP_OUT_ERR(-1, "Unknown algorithm\n");
927 }976 }
928977
929 HIP_IFEL(!X509_sign(cert, pkey, digest), -1,978 /* Get the issuer key for signing */
979 HIP_IFEL(hip_get_host_id_and_priv_key(issuer_hit_n, HIP_ANY_ALGO,
980 &host_id, &key),
981 -1, "Private key not found\n");
982
983 switch (host_id->rdata.algorithm) {
984 case HIP_HI_RSA:
985 HIP_IFEL(!EVP_PKEY_set1_RSA(sig_key, key), -1,
986 "Failed to convert RSA to EVP_PKEY\n");
987 break;
988 case HIP_HI_DSA:
989 HIP_IFEL(!EVP_PKEY_set1_DSA(sig_key, key), -1,
990 "Failed to convert DSA to EVP_PKEY\n");
991 break;
992 default:
993 HIP_OUT_ERR(-1, "Unknown algorithm\n");
994 }
995
996 HIP_IFEL(!X509_sign(cert, sig_key, digest), -1,
930 "Failed to sign x509v3 certificate\n");997 "Failed to sign x509v3 certificate\n");
931998
932 /** DER */999 /** DER */
@@ -943,8 +1010,15 @@
9431010
944out_err:1011out_err:
945 free(host_id);1012 free(host_id);
946 X509_REQ_free(req);
947 sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);1013 sk_X509_EXTENSION_pop_free(extlist, X509_EXTENSION_free);
1014 X509_NAME_ENTRY_free(ent);
1015 X509_NAME_free(subj);
1016 X509_NAME_free(issuer);
1017 NCONF_free(conf);
1018 ERR_free_strings();
1019 EVP_PKEY_free(pkey);
1020 EVP_PKEY_free(sig_key);
1021 free(issuer_hit_n);
948 return err;1022 return err;
949}1023}
9501024
@@ -985,7 +1059,7 @@
985 der_cert = (unsigned char *) &p->der;1059 der_cert = (unsigned char *) &p->der;
9861060
987 vessel = p->der;1061 vessel = p->der;
988 HIP_IFEL((cert = d2i_X509(NULL, &vessel, verify.der_len)) == NULL, -1,1062 HIP_IFEL((cert = d2i_X509(NULL, &vessel, ntohl(verify.der_len))) == NULL, -1,
989 "Failed to convert cert from DER to internal format\n");1063 "Failed to convert cert from DER to internal format\n");
990 /*1064 /*
991 * HIP_IFEL(!X509_print_fp(stdout, cert), -1,1065 * HIP_IFEL(!X509_print_fp(stdout, cert), -1,
9921066
=== modified file 'hipd/input.c'
--- hipd/input.c 2012-03-08 12:28:00 +0000
+++ hipd/input.c 2012-03-09 12:45:28 +0000
@@ -73,7 +73,6 @@
73#include "netdev.h"73#include "netdev.h"
74#include "opp_mode.h"74#include "opp_mode.h"
75#include "output.h"75#include "output.h"
76#include "pisa.h"
77#include "pkt_handling.h"76#include "pkt_handling.h"
78#include "registration.h"77#include "registration.h"
79#include "input.h"78#include "input.h"
8079
=== modified file 'hipd/output.c'
--- hipd/output.c 2012-03-01 14:06:24 +0000
+++ hipd/output.c 2012-03-09 12:45:28 +0000
@@ -65,7 +65,6 @@
65#include "hiprelay.h"65#include "hiprelay.h"
66#include "nat.h"66#include "nat.h"
67#include "netdev.h"67#include "netdev.h"
68#include "pisa.h"
69#include "registration.h"68#include "registration.h"
70#include "output.h"69#include "output.h"
7170
7271
=== renamed file 'hipfw/pisa.c' => 'hipfw/cert.c'
--- hipfw/pisa.c 2011-11-25 13:52:20 +0000
+++ hipfw/cert.c 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -25,551 +25,190 @@
2525
26/**26/**
27 * @file27 * @file
28 * This file contains PISA specific functions for the firewall. The basic idea28 * certifcate functionality for the firewall
29 * is to modify the HIP messages and manage state for allowed connections to
30 * allow or reject associated ESP traffic.
31 *29 *
32 * @brief PISA functions for the firewall30 * @brief certificate functions for the firewall
33 */31 */
3432
35#define _BSD_SOURCE33#define _BSD_SOURCE
3634
35#include <limits.h>
37#include <stdint.h>36#include <stdint.h>
38#include <stdio.h>37#include <stdio.h>
39#include <stdlib.h>38#include <stdlib.h>
40#include <string.h>39#include <string.h>
41#include <time.h>
42#include <arpa/inet.h>
43#include <netinet/in.h>40#include <netinet/in.h>
44#include <linux/netfilter.h>41#include <linux/netfilter.h>
45#include <openssl/hmac.h>42#include <linux/netfilter_ipv6.h>
43#include <openssl/x509.h>
4644
47#include "config.h"45#include "lib/core/common.h"
46#include "lib/core/ife.h"
48#include "lib/core/builder.h"47#include "lib/core/builder.h"
49#include "lib/core/certtools.h"48#include "lib/core/cert.h"
50#include "lib/core/crypto.h"
51#include "lib/core/debug.h"49#include "lib/core/debug.h"
52#include "lib/core/ife.h"
53#include "lib/core/performance.h"
54#include "lib/core/prefix.h"
55#include "modules/midauth/hipd/midauth.h"
56#include "conntrack.h"50#include "conntrack.h"
57#include "hipfw_defines.h"51#include "hipfw_defines.h"
58#include "midauth.h"52#include "rule_management.h"
59#include "pisa_cert.h"53#include "cert.h"
60#include "pisa.h"54
6155// runtime configuration
6256static int use_cert = false;
63#define PISA_RANDOM_LEN 1657
64#define PISA_PUZZLE_SEED 0xDEADC0DE58static STACK_OF(X509) *root_chain = NULL;
65#define PISA_PUZZLE_OPAQUE_LEN (4 + HIP_AH_SHA_LEN)59
6660/**
67/* pisa_check_for_random_update is called at least every PISA_RANDOM_TTL61 * Init function for certificate functionality.
68 * seconds. Worst case timer resolution depends on the timeout in the select62 *
69 * call */63 * Iterate the firewall rules and look for the cert option. If found,
70#define PISA_RANDOM_TTL 2.064 * certificates are used and the root certificate is preloaded to verify
7165 * certificates. If no such rule is found, certificates are deactivated.
72static char pisa_random_data[2][PISA_RANDOM_LEN];66 *
73static struct in6_addr community_operator_hit;67 * @return 0 on success, negative if an error occurred
7468 */
75/* @todo make this configurable, issuer HIT */69int cert_init(void)
76#define CO_HIT "2001:001a:b1b0:0aad:0f92:15ca:280c:9430"70{
77#define CO_HIT_FILE HIPL_SYSCONFDIR "/co_hit"71 X509 *cert = NULL;
7872 struct rule *rule = NULL;
79/**73 struct dlist *list = NULL;
80 * Generate a new random number and shift the old one down.74
81 */75 if (!(list = get_rule_list(NF_IP6_FORWARD))) {
82static void pisa_generate_random(void)76 use_cert = false;
83{77 HIP_DEBUG("certificates deactivated\n");
84 void *p0, *p1;
85
86 p0 = &pisa_random_data[0][0];
87 p1 = &pisa_random_data[1][0];
88
89 memcpy(p0, p1, PISA_RANDOM_LEN);
90 get_random_bytes(p1, PISA_RANDOM_LEN);
91}
92
93/**
94 * Reads out the HIT of the Community-Operator
95 * from file CO_HIT_FILE
96 * @param hit A pointer to the char where the HIT should be stored
97 * @return 1-> success
98 * @return 0-> error
99 */
100static int pisa_read_communit_operator_hit(char *hit)
101{
102 FILE *f;
103 char *eofline;
104
105 f = fopen(CO_HIT_FILE, "r");
106
107 if (f == NULL) {
108 return 0;78 return 0;
109 }79 }
11080
111 if (fgets(hit, INET6_ADDRSTRLEN, f) != NULL) {81 if (!(root_chain = sk_X509_new_null())) {
112 eofline = strchr(hit, '\n');82 HIP_ERROR("Memory allocation failure.\n");
113 if (eofline) {83 return -ENOMEM;
114 *eofline = '\0';84 }
115 }85
116 } else {86 /* Search for rules with cert option */
117 HIP_ERROR("Fgets failed");87 while (list) {
118 }88 rule = list->data;
119 fclose(f);89 if (rule->cert) {
12090 HIP_DEBUG("allowed cert: %s\n", rule->cert->value);
121 return 1;91 use_cert = true;
122}92 if (!(cert = cert_load_x509_certificate(rule->cert->value,
12393 ENCODING_FORMAT_PEM))) {
124void pisa_check_for_random_update(void)94 HIP_ERROR("Could not load certificate of community operator from file: %s \n",
125{95 rule->cert->value);
126 static time_t lastupdate = 0;96 return -1;
127 time_t now;
128
129 time(&now);
130 if (difftime(now, lastupdate) > PISA_RANDOM_TTL) {
131 pisa_generate_random();
132 lastupdate = now;
133 }
134}
135
136/**
137 * Appends HMAC/SHA1 to a block of data.
138 *
139 * @param hit1 first HIT
140 * @param hit2 second HIT
141 * @param rnd which random number to use, either 0 or 1
142 * @param data pointer to buffer for data and the HMAC
143 * @param data_len length of data
144 * @return 0 on success
145 */
146static int pisa_append_hmac(struct in6_addr *hit1, struct in6_addr *hit2,
147 int rnd, void *data, int data_len)
148{
149 uint8_t key[32 + PISA_RANDOM_LEN];
150 int err = 0;
151 unsigned int len = HIP_AH_SHA_LEN;
152
153 /* sanity checks for arguments */
154 HIP_IFEL(data == NULL, -1, "No data given.\n");
155 HIP_IFEL(hit1 == NULL, -1, "No first HIT given.\n");
156 HIP_IFEL(hit2 == NULL, -1, "No second HIT given.\n");
157 HIP_IFEL(data_len < 1, -1, "Data has invalid length.\n");
158 HIP_IFEL(rnd != 0 && rnd != 1, -1, "Random ID is neither 0 nor 1.\n");
159
160 /* The key for HMAC/SHA1 consists of:
161 * 16 bytes HIT1
162 * 16 bytes HIT2
163 * PISA_RANDOM_LEN bytes pisa_random_data
164 */
165
166 ipv6_addr_copy((struct in6_addr *) (key + 0), hit1);
167 ipv6_addr_copy((struct in6_addr *) (key + 16), hit2);
168 memcpy(key + 32, &pisa_random_data[rnd][0], PISA_RANDOM_LEN);
169
170 HMAC(EVP_sha1(), key, 32 + PISA_RANDOM_LEN, data, data_len,
171 (uint8_t *) data + data_len, &len);
172
173out_err:
174 return err;
175}
176
177/**
178 * Insert a PISA puzzle into a packet.
179 *
180 * @param ctx context of the packet where the puzzle will be inserted
181 * @return success (0) or failure
182 */
183static int pisa_insert_puzzle(struct hip_fw_context *ctx)
184{
185 uint8_t opaque[PISA_PUZZLE_OPAQUE_LEN];
186
187 struct hip_common *hip = ctx->transport_hdr.hip;
188 int seed = PISA_PUZZLE_SEED;
189
190 memcpy(&opaque, &seed, 4);
191
192 /* here we switch order of initiator and receiver to obtain a
193 * different SHA1 hash */
194 pisa_append_hmac(&hip->hitr, &hip->hits, 1, &opaque, 4);
195
196 return midauth_add_challenge_request(ctx, 3, 4, opaque, PISA_PUZZLE_OPAQUE_LEN);
197}
198
199/**
200 * Check the validity of a PISA challenge_response.
201 *
202 * @param ctx context of the packet with the puzzle to check
203 * @return pointer to the puzzle we accepted or NULL at failure
204 */
205static struct hip_challenge_response *pisa_check_challenge_response(struct hip_fw_context *ctx)
206{
207 struct hip_challenge_response *response;
208 struct hip_common *hip = ctx->transport_hdr.hip;
209 uint8_t hash[2][PISA_PUZZLE_OPAQUE_LEN];
210 int seed = PISA_PUZZLE_SEED;
211
212 memcpy(&hash[0][0], &seed, 4);
213 memcpy(&hash[1][0], &seed, 4);
214
215 pisa_append_hmac(&hip->hits, &hip->hitr, 0, &hash[0], 4);
216 pisa_append_hmac(&hip->hits, &hip->hitr, 1, &hash[1], 4);
217
218 response = hip_get_param_readwrite(hip, HIP_PARAM_CHALLENGE_RESPONSE);
219
220 while (response) {
221 /* loop over all HIP_PARAM_CHALLENGE_RESPONSE */
222 if (hip_get_param_type(response) != HIP_PARAM_CHALLENGE_RESPONSE) {
223 break;
224 }
225 if ((!memcmp(response->opaque, &hash[1][0], PISA_PUZZLE_OPAQUE_LEN)) ||
226 (!memcmp(response->opaque, &hash[0][0], PISA_PUZZLE_OPAQUE_LEN))) {
227 if (!midauth_verify_challenge_response(response,
228 hip->hits,
229 hip->hitr)) {
230 return response;
231 }97 }
232 }98 sk_X509_push(root_chain, cert);
23399 }
234 response = (struct hip_challenge_response *)100 list = list->next;
235 hip_get_next_param_readwrite(hip,101 }
236 (struct hip_tlv_common *) response);102
237 }103 if (use_cert) {
238104 HIP_DEBUG("certificates activated\n");
239 return NULL;105 }
240}106
241107 return 0;
242/**108}
243 * Check the certificate of the packet.109
244 *110/**
245 * @param ctx context of the packet with the certificate to check111 * Uninit function for certificate functionality.
246 * @return success (0) or failure112 *
247 */113 * @return 0
248static int pisa_check_certificate(struct hip_fw_context *ctx)114 */
249{115int cert_uninit(void)
250 struct hip_common *hip = ctx->transport_hdr.hip;116{
251 const struct hip_cert *cert;117 sk_X509_free(root_chain);
252 struct hip_cert_spki_info ci;118 return 0;
253 struct pisa_cert pc;119}
254 char *buf = NULL;120
255 int err = 0, len;121/**
256 time_t now = time(NULL);122 * Helper function that converts the special RSA and DSA key structures
257123 * to the generic EVP_PKEY structure.
258 cert = hip_get_param(hip, HIP_PARAM_CERT);124 *
259 HIP_IFEL(cert == NULL, -1, "No certificate found.\n");125 * @param key the RSA or DSA key structure
260126 * @param algo either HIP_HI_RSA or HIP_HI_DSA
261 len = ntohs(cert->length);127 *
262 buf = calloc(1, len);128 * @return the EVP_PKEY structure that wraps the original key,
263 memcpy(buf, cert + 1, len);129 * or NULL on error
264130 */
265 HIP_IFEL(hip_cert_spki_char2certinfo(buf, &ci), -1,131static EVP_PKEY *any_key_to_evp_key(void *key, int algo)
266 "Certificate could not be parsed.\n");132{
267 HIP_IFEL(hip_cert_spki_lib_verify(&ci), -1,133 int err = 0;
268 "Certificate could not be verified.\n");134 EVP_PKEY *ret = NULL;
269135
270 pisa_split_cert(ci.cert, &pc);136 if (!(ret = EVP_PKEY_new())) {
271137 HIP_ERROR("Could not init EVP_PKEY wrapper\n");
272 /* Three conditions must be fulfilled for a certificate to be valid:138 return NULL;
273 *139 }
274 * - The current time on the middlebox must be in the before/after140
275 * interval141 switch (algo) {
276 * - The certificate must be issued by the community operator (i.e.142 case HIP_HI_RSA:
277 * the CO HIT must be used by the issuer)143 err = EVP_PKEY_assign_RSA(ret, key);
278 * - The host sending the certificate must be the one mentioned in144 break;
279 * the certificate145 case HIP_HI_DSA:
280 */146 err = EVP_PKEY_assign_DSA(ret, key);
281 HIP_IFEL(now < pc.not_before, -1,147 break;
282 "Certificate is not valid yet.\n");148 default:
283 HIP_IFEL(now > pc.not_after, -1,149 HIP_DEBUG("Unknown algorithm \n");
284 "Certificate has expired.\n");150 }
285151 if (err == 0) {
286152 HIP_ERROR("Could not assign key to EVP_PKEY.\n");
287 HIP_IFEL(ipv6_addr_cmp(&pc.hit_issuer, &community_operator_hit) != 0,153 EVP_PKEY_free(ret);
288 -1, "Certificate not issued by the community operator.\n");154 return NULL;
289 HIP_IFEL(ipv6_addr_cmp(&pc.hit_subject, &hip->hits) != 0, -1,155 }
290 "Certificate does not belong to subject.\n");156
291157 return ret;
292 HIP_INFO("Certificate successfully verified.\n");158}
293159
294out_err:160/**
295 free(buf);161 * Extract the certificate from the R2 packet and match the contained public
296 return err;162 * key against the HI provided in the R1 and try to build and verify
297}163 * a certificate chain.
298164 *
299/**165 * For an update exchange, a certificate must be contained either in the U2
300 * Accept a connection via PISA. Update firewall to allow data packets to166 * (if the exchange was started by the Initiator) or in the U3
301 * pass through.167 * (if the exchange was started by the Responder). If a certificate cannot be
302 *168 * found in these situations an error is returned.
303 * @param ctx context of the packet that belongs to that connection169 *
304 */170 * @param common the R2 or U2 packet
305static void pisa_accept_connection(const struct hip_fw_context *ctx)171 * @param tuple the connection tracking tuple
306{172 * @param ctx the firewall context
307 struct hip_common *hip = ctx->transport_hdr.hip;173 * @return 0 on success, negative error code otherwise
308 struct tuple *t = get_tuple_by_hits(&hip->hits, &hip->hitr);174 */
309175int cert_handle_certificate(const struct hip_common *const common,
310 if (t) {176 UNUSED struct tuple *const tuple,
311 t->connection->pisa_state = PISA_STATE_ALLOW;177 UNUSED const struct hip_fw_context *const ctx)
312 HIP_INFO("PISA accepted the connection.\n");178{
313 hip_fw_manage_all_esp_tuples(t, true);179 X509 *cert = NULL;
314 } else {180 EVP_PKEY *pkey = NULL;
315 HIP_ERROR("Connection not found.\n");181
316 }182 if (use_cert) {
317}183 /* Should there be a certificate?
318184 * Not if this update is not sent by the Responder. */
319/**185 if (!(tuple->direction == REPLY_DIR)) {
320 * Remove a connection from the list of accepted connections based on the hits186 return 0;
321 * of a packet.187 }
322 *188
323 * @param ctx context of the packet that contains HITs of the connection189 /* Extract certificate of trust point from the packet. */
324 */190 if (!(cert = cert_get_X509_from_msg(common))) {
325static void pisa_remove_connection(const struct hip_fw_context *ctx)191 HIP_DEBUG("Could not find trust-point certificate in R2/U2.\n");
326{192 return -1;
327 struct hip_common *hip = ctx->transport_hdr.hip;193 }
328 struct tuple *t = get_tuple_by_hits(&hip->hits, &hip->hitr);194
329195 /* Match HI against public key in given certificate. */
330 if (t) {196 pkey = any_key_to_evp_key(tuple->hip_tuple->data->src_pub_key,
331 t->connection->pisa_state = PISA_STATE_DISALLOW;197 hip_get_host_id_algo(tuple->hip_tuple->data->src_hi));
332 HIP_INFO("PISA removed the connection.\n");198 if (!cert_match_public_key(cert, pkey)) {
333 hip_fw_manage_all_esp_tuples(t, false);199 HIP_ERROR("HI does not match public key in given certificate.\n");
334 } else {200 return -1;
335 HIP_ERROR("Connection not found.\n");201 }
336 }202 HIP_DEBUG("HI matches given certificate.\n");
337}203
338204 /* Check certificate of trust point. */
339/**205 if (cert_verify_chain(cert, NULL, root_chain, NULL)) {
340 * Reject a connection via PISA. Update firewall to allow no data packets206 HIP_ERROR("Could not verify trust point certificate.\n");
341 * to pass through.207 return -1;
342 *208 }
343 * @param ctx context of the packet that belongs to that connection209
344 */210 HIP_DEBUG("Verified trust-point certificate.\n");
345static void pisa_reject_connection(const struct hip_fw_context *ctx)211 }
346{212
347 HIP_INFO("PISA rejected the connection.\n");213 return 0;
348 pisa_remove_connection(ctx);
349}
350
351/**
352 * Dummy function, necessary only for performance measurements.
353 *
354 * @param ctx context of the packet containing the I1
355 * @return NF_ACCEPT verdict
356 */
357static int pisa_handler_i1(UNUSED struct hip_fw_context *ctx)
358{
359#ifdef CONFIG_HIP_PERFORMANCE
360 HIP_DEBUG("Start PERF_BASE, PERF_I1\n");
361 hip_perf_start_benchmark(perf_set, PERF_BASE);
362 hip_perf_start_benchmark(perf_set, PERF_I1);
363#endif
364
365#ifdef CONFIG_HIP_PERFORMANCE
366 HIP_DEBUG("Stop and write PERF_I1\n");
367 hip_perf_stop_benchmark(perf_set, PERF_I1);
368 hip_perf_write_benchmark(perf_set, PERF_I1);
369#endif
370
371 return NF_ACCEPT;
372}
373
374/**
375 * Dummy function, necessary only for performance measurements.
376 *
377 * @param ctx context of the packet containing the R1
378 * @return NF_ACCEPT verdict
379 */
380static int pisa_handler_r1(UNUSED struct hip_fw_context *ctx)
381{
382#ifdef CONFIG_HIP_PERFORMANCE
383 HIP_DEBUG("Start PERF_R1\n");
384 hip_perf_start_benchmark(perf_set, PERF_R1);
385#endif
386
387#ifdef CONFIG_HIP_PERFORMANCE
388 HIP_DEBUG("Stop and write PERF_R1\n");
389 hip_perf_stop_benchmark(perf_set, PERF_R1);
390 hip_perf_write_benchmark(perf_set, PERF_R1);
391#endif
392
393 return NF_ACCEPT;
394}
395
396/**
397 * Insert a PISA puzzle into the I2 packet.
398 *
399 * @param ctx context of the packet to modify
400 * @return NF_ACCEPT verdict
401 */
402static int pisa_handler_i2(struct hip_fw_context *ctx)
403{
404#ifdef CONFIG_HIP_PERFORMANCE
405 HIP_DEBUG("Start PERF_I2\n");
406 hip_perf_start_benchmark(perf_set, PERF_I2);
407#endif
408 pisa_insert_puzzle(ctx);
409
410#ifdef CONFIG_HIP_PERFORMANCE
411 HIP_DEBUG("Stop and write PERF_I2\n");
412 hip_perf_stop_benchmark(perf_set, PERF_I2);
413 hip_perf_write_benchmark(perf_set, PERF_I2);
414#endif
415
416 return NF_ACCEPT;
417}
418
419/**
420 * Check for a PISA puzzle, a valid signature and a valid
421 * certificate in the R2 packet.
422 *
423 * @param ctx context of the packet to check
424 * @return verdict, either NF_ACCEPT or NF_DROP
425 */
426static int pisa_handler_r2(struct hip_fw_context *ctx)
427{
428 int verdict = NF_DROP, sig = 0, cert = 0;
429 struct hip_challenge_response *solution = NULL;
430
431#ifdef CONFIG_HIP_PERFORMANCE
432 HIP_DEBUG("Start PERF_R2\n");
433 hip_perf_start_benchmark(perf_set, PERF_R2);
434#endif
435
436 solution = pisa_check_challenge_response(ctx);
437 cert = pisa_check_certificate(ctx);
438
439 if (solution == NULL || sig != 0 || cert != 0) {
440 /* disallow further communication if either nonce, solution,
441 * signature or certificate were not correct */
442 pisa_reject_connection(ctx);
443 verdict = NF_DROP;
444 } else {
445 /* allow futher communication otherwise */
446 pisa_accept_connection(ctx);
447 verdict = NF_ACCEPT;
448 }
449
450#ifdef CONFIG_HIP_PERFORMANCE
451 HIP_DEBUG("Stop and write PERF_R2, PERF_BASE\n");
452 hip_perf_stop_benchmark(perf_set, PERF_R2);
453 hip_perf_stop_benchmark(perf_set, PERF_BASE);
454 hip_perf_write_benchmark(perf_set, PERF_R2);
455 hip_perf_write_benchmark(perf_set, PERF_BASE);
456#endif
457
458 return verdict;
459}
460
461/**
462 * Insert a PISA nonce and a PISA puzzle into the U1 packet.
463 *
464 * @param ctx context of the packet to modify
465 * @return NF_ACCEPT verdict
466 */
467static int pisa_handler_u1(struct hip_fw_context *ctx)
468{
469 pisa_insert_puzzle(ctx);
470
471 return NF_ACCEPT;
472}
473
474/**
475 * Check for a PISA nonce, a PISA puzzle, a valid signature and a valid
476 * certificate in the U2 packet.
477 *
478 * @param ctx context of the packet to check
479 * @return verdict, either NF_ACCEPT or NF_DROP
480 */
481static int pisa_handler_u2(struct hip_fw_context *ctx)
482{
483 int verdict = NF_DROP;
484 int sig = 0;
485 int cert = 0;
486 struct hip_challenge_response *solution = NULL;
487
488 solution = pisa_check_challenge_response(ctx);
489 cert = pisa_check_certificate(ctx);
490
491 if (solution == NULL || sig != 0 || cert != 0) {
492 HIP_DEBUG("U2 packet did not match criteria: "
493 "solution %p, signature %i, cert %i\n",
494 solution, sig, cert);
495 verdict = NF_DROP;
496 } else {
497 /* packet was ok, insert another puzzle */
498 pisa_insert_puzzle(ctx);
499 verdict = NF_ACCEPT;
500 }
501
502 return verdict;
503}
504
505/**
506 * Check for a PISA nonce and a valid signature in the U3 packet.
507 *
508 * @param ctx context of the packet to check
509 * @return verdict, either NF_ACCEPT or NF_DROP
510 */
511static int pisa_handler_u3(struct hip_fw_context *ctx)
512{
513 int verdict = NF_DROP;
514 int sig = 0;
515 struct hip_challenge_response *solution = NULL;
516
517 solution = pisa_check_challenge_response(ctx);
518
519 if (solution == NULL || sig != 0) {
520 HIP_DEBUG("U2 packet did not match criteria: "
521 "solution %p\n",
522 solution);
523 pisa_reject_connection(ctx);
524 verdict = NF_DROP;
525 } else {
526 pisa_accept_connection(ctx);
527 verdict = NF_ACCEPT;
528 }
529 return verdict;
530}
531
532/**
533 * Handle CLOSE_ACK packet. Remove the connection from the list of accepted
534 * connections
535 *
536 * @param ctx context of the packet
537 * @return verdict, either NF_ACCEPT or NF_DROP
538 */
539static int pisa_handler_close_ack(struct hip_fw_context *ctx)
540{
541 pisa_remove_connection(ctx);
542 return NF_ACCEPT;
543}
544
545/**
546 * Initialize basic PISA functionality
547 *
548 * @param h function pointers for packet handlers
549 */
550void pisa_init(struct midauth_handlers *h)
551{
552 char hit[INET6_ADDRSTRLEN];
553 h->i1 = pisa_handler_i1;
554 h->r1 = pisa_handler_r1;
555 h->i2 = pisa_handler_i2;
556 h->r2 = pisa_handler_r2;
557 h->u1 = pisa_handler_u1;
558 h->u2 = pisa_handler_u2;
559 h->u3 = pisa_handler_u3;
560 h->close = midauth_handler_accept;
561 h->close_ack = pisa_handler_close_ack;
562
563 pisa_generate_random();
564 pisa_generate_random();
565
566 if (!pisa_read_communit_operator_hit(hit)) {
567 hit[0] = '\0';
568 HIP_ERROR("Could not load Communit-Operator HIT from file %s\n",
569 CO_HIT_FILE);
570 }
571
572 if (inet_pton(AF_INET6, hit, &community_operator_hit) <= 0) {
573 HIP_ERROR("Coult not parse Community-Operator HIT\n");
574 }
575}214}
576215
=== renamed file 'hipfw/pisa.h' => 'hipfw/cert.h'
--- hipfw/pisa.h 2011-11-25 13:52:20 +0000
+++ hipfw/cert.h 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -23,26 +23,16 @@
23 * OTHER DEALINGS IN THE SOFTWARE.23 * OTHER DEALINGS IN THE SOFTWARE.
24 */24 */
2525
26#ifndef HIPL_HIPFW_PISA_H26#ifndef HIPL_HIPFW_CERT_H
27#define HIPL_HIPFW_PISA_H27#define HIPL_HIPFW_CERT_H
2828
29#include "midauth.h"29#include "hipfw_defines.h"
3030
31#define PISA_STATE_DISALLOW 031int cert_init(void);
32#define PISA_STATE_ALLOW 132int cert_uninit(void);
3333
34#ifdef CONFIG_HIP_PISA34int cert_handle_certificate(const struct hip_common *const common,
35/**35 struct tuple *const tuple,
36 * Register PISA handlers with midauth and initialize data structures.36 const struct hip_fw_context *const ctx);
37 *37
38 * @param h pointer to the handlers38#endif /* HIPL_HIPFW_CERT_H */
39 */
40void pisa_init(struct midauth_handlers *h);
41#endif
42
43/**
44 * Check if a new random number is necessary.
45 */
46void pisa_check_for_random_update(void);
47
48#endif /* HIPL_HIPFW_PISA_H */
4939
=== modified file 'hipfw/conntrack.c'
--- hipfw/conntrack.c 2012-03-08 14:33:33 +0000
+++ hipfw/conntrack.c 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -62,8 +62,9 @@
62#include "lib/core/state.h"62#include "lib/core/state.h"
63#include "lib/core/gpl/pk.h"63#include "lib/core/gpl/pk.h"
64#include "modules/update/hipd/update.h"64#include "modules/update/hipd/update.h"
65#include "config.h"
66#include "cert.h"
65#include "common_types.h"67#include "common_types.h"
66#include "config.h"
67#include "conntrack.h"68#include "conntrack.h"
68#include "dlist.h"69#include "dlist.h"
69#include "hslist.h"70#include "hslist.h"
@@ -72,7 +73,7 @@
72#include "hipfw.h"73#include "hipfw.h"
73#include "helpers.h"74#include "helpers.h"
74#include "hslist.h"75#include "hslist.h"
75#include "pisa.h"76#include "midauth.h"
76#include "reinject.h"77#include "reinject.h"
7778
7879
@@ -1296,6 +1297,11 @@
1296 return 0;1297 return 0;
1297 }1298 }
12981299
1300 if (cert_handle_certificate(common, tuple, ctx)) {
1301 HIP_ERROR("certificate error on R2\n");
1302 return 0;
1303 }
1304
1299 /* check if the R2 contains ESP protection anchor and store state */1305 /* check if the R2 contains ESP protection anchor and store state */
1300 if (esp_prot_conntrack_R2_anchor(common, tuple)) {1306 if (esp_prot_conntrack_R2_anchor(common, tuple)) {
1301 HIP_ERROR("failed to track esp protection extension state\n");1307 HIP_ERROR("failed to track esp protection extension state\n");
@@ -1330,7 +1336,7 @@
1330 uint8_t locator_type;1336 uint8_t locator_type;
13311337
1332 ptr = (const char *) (locator + 1);1338 ptr = (const char *) (locator + 1);
1333 while (ptr < ptr + hip_get_param_contents_len(locator)) {1339 while (ptr < ((const char *) (locator + 1)) + hip_get_param_contents_len(locator)) {
1334 locator_type = ((const struct hip_locator_type_0 *) ptr)->header.locator_type;1340 locator_type = ((const struct hip_locator_type_0 *) ptr)->header.locator_type;
1335 if (locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) {1341 if (locator_type == HIP_LOCATOR_LOCATOR_TYPE_IPV6) {
1336 esp_dest_addr = &((const struct hip_locator_type_0 *) ptr)->address;1342 esp_dest_addr = &((const struct hip_locator_type_0 *) ptr)->address;
@@ -1368,11 +1374,6 @@
1368{1374{
1369 int err = 1;1375 int err = 1;
13701376
1371 if (hip_get_param_total_len(locator) - sizeof(struct hip_locator) < sizeof(struct hip_locator_type_0)) {
1372 HIP_ERROR("no locator param found\n");
1373 return 0;
1374 }
1375
1376 if (esp_info && locator && seq) {1377 if (esp_info && locator && seq) {
1377 HIP_DEBUG("esp_info, locator and seq\n");1378 HIP_DEBUG("esp_info, locator and seq\n");
13781379
@@ -1386,6 +1387,11 @@
1386 esp_tuple->spi = ntohl(esp_info->new_spi);1387 esp_tuple->spi = ntohl(esp_info->new_spi);
1387 esp_tuple->spi_update_id = seq->update_id;1388 esp_tuple->spi_update_id = seq->update_id;
13881389
1390 if (hip_get_param_total_len(locator) - sizeof(struct hip_locator) < sizeof(struct hip_locator_type_0)) {
1391 HIP_ERROR("no locator param found\n");
1392 return 0;
1393 }
1394
1389 HIP_IFEL(!update_esp_dest_addr(locator, seq, esp_tuple),1395 HIP_IFEL(!update_esp_dest_addr(locator, seq, esp_tuple),
1390 0, "error updateing ESP destination addresses\n");1396 0, "error updateing ESP destination addresses\n");
1391 } else if (esp_info && seq) {1397 } else if (esp_info && seq) {
@@ -1597,6 +1603,11 @@
1597 return 0;1603 return 0;
1598 }1604 }
15991605
1606 if (cert_handle_certificate(common, tuple, ctx)) {
1607 HIP_ERROR("certificate error on U2\n");
1608 return 0;
1609 }
1610
1600 if (handle_second_update(tuple, ctx, esp_info, seq)) {1611 if (handle_second_update(tuple, ctx, esp_info, seq)) {
1601 HIP_ERROR("unable to process second UPDATE message\n");1612 HIP_ERROR("unable to process second UPDATE message\n");
1602 return 0;1613 return 0;
16031614
=== modified file 'hipfw/hipfw.c'
--- hipfw/hipfw.c 2012-03-08 12:28:00 +0000
+++ hipfw/hipfw.c 2012-03-09 12:45:28 +0000
@@ -78,6 +78,7 @@
78#include "hipd/hipd.h"78#include "hipd/hipd.h"
79#include "config.h"79#include "config.h"
80#include "cache.h"80#include "cache.h"
81#include "cert.h"
81#include "common_types.h"82#include "common_types.h"
82#include "conntrack.h"83#include "conntrack.h"
83#include "esp_prot_api.h"84#include "esp_prot_api.h"
@@ -87,7 +88,6 @@
87#include "helpers.h"88#include "helpers.h"
88#include "lsi.h"89#include "lsi.h"
89#include "midauth.h"90#include "midauth.h"
90#include "pisa.h"
91#include "port_bindings.h"91#include "port_bindings.h"
92#include "reinject.h"92#include "reinject.h"
93#include "rewrite.h"93#include "rewrite.h"
@@ -481,6 +481,8 @@
481481
482 midauth_init();482 midauth_init();
483483
484 HIP_IFEL(cert_init(), -1, "failed to load extension (cert)\n");
485
484 // Initializing local port cache database486 // Initializing local port cache database
485 hip_port_bindings_init(true);487 hip_port_bindings_init(true);
486 /* Initialize raw sockets for packet reinjection */488 /* Initialize raw sockets for packet reinjection */
@@ -628,6 +630,8 @@
628 fw_uninit_lsi_support();630 fw_uninit_lsi_support();
629 hip_fw_uninit_conntrack();631 hip_fw_uninit_conntrack();
630632
633 cert_uninit();
634
631#ifdef CONFIG_HIP_PERFORMANCE635#ifdef CONFIG_HIP_PERFORMANCE
632 /* Deallocate memory of perf_set after finishing all of tests */636 /* Deallocate memory of perf_set after finishing all of tests */
633 hip_perf_destroy(perf_set);637 hip_perf_destroy(perf_set);
@@ -1876,12 +1880,6 @@
1876 continue;1880 continue;
1877 }1881 }
18781882
1879#ifdef CONFIG_HIP_PISA
1880 if (use_midauth) {
1881 pisa_check_for_random_update();
1882 }
1883#endif
1884
1885 if (FD_ISSET(h4->fd, &read_fdset)) {1883 if (FD_ISSET(h4->fd, &read_fdset)) {
1886 HIP_DEBUG("received IPv4 packet from iptables queue\n");1884 HIP_DEBUG("received IPv4 packet from iptables queue\n");
1887 err = fw_handle_packet(buf, h4, 4, &ctx);1885 err = fw_handle_packet(buf, h4, 4, &ctx);
18881886
=== modified file 'hipfw/hipfw.conf'
--- hipfw/hipfw.conf 2011-12-15 13:25:00 +0000
+++ hipfw/hipfw.conf 2012-03-09 12:45:28 +0000
@@ -7,5 +7,6 @@
7# -i [!] <incoming interface>7# -i [!] <incoming interface>
8# -o [!] <outgoing interface>8# -o [!] <outgoing interface>
9# -state [!] <state> --verify_responder --accept_mobile --decrypt_contents9# -state [!] <state> --verify_responder --accept_mobile --decrypt_contents
10# -cert <root certificate>"
10#11#
1112
1213
=== modified file 'hipfw/hipfw_defines.h'
--- hipfw/hipfw_defines.h 2012-02-17 18:01:18 +0000
+++ hipfw/hipfw_defines.h 2012-03-09 12:45:28 +0000
@@ -158,7 +158,6 @@
158 /* members needed for ESP protection extension */158 /* members needed for ESP protection extension */
159 int num_esp_prot_tfms;159 int num_esp_prot_tfms;
160 uint8_t esp_prot_tfms[MAX_NUM_TRANSFORMS];160 uint8_t esp_prot_tfms[MAX_NUM_TRANSFORMS];
161 int pisa_state;
162};161};
163162
164#endif /* HIPL_HIPFW_FIREWALL_DEFINES_H */163#endif /* HIPL_HIPFW_FIREWALL_DEFINES_H */
165164
=== modified file 'hipfw/main.c'
--- hipfw/main.c 2011-11-25 13:52:20 +0000
+++ hipfw/main.c 2012-03-09 12:45:28 +0000
@@ -37,14 +37,15 @@
3737
38#include <stdio.h>38#include <stdio.h>
39#include <stdlib.h>39#include <stdlib.h>
40#include <string.h>
40#include <unistd.h>41#include <unistd.h>
41#include <sys/types.h>42#include <sys/types.h>
4243
43#include "lib/core/filemanip.h"44#include "lib/core/filemanip.h"
44#include "lib/core/debug.h"45#include "lib/core/debug.h"
45#include "lib/core/util.h"46#include "lib/core/util.h"
47#include "conntrack.h"
46#include "hipfw.h"48#include "hipfw.h"
47#include "conntrack.h"
48#include "midauth.h"49#include "midauth.h"
4950
5051
5152
=== removed file 'hipfw/pisa_cert.c'
--- hipfw/pisa_cert.c 2011-08-15 14:11:56 +0000
+++ hipfw/pisa_cert.c 1970-01-01 00:00:00 +0000
@@ -1,205 +0,0 @@
1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * @file
28 * This file deals with the PISA specific handling of SPKI certificates. The
29 * certificate is parsed and split into small chunks.
30 *
31 * @brief PISA handling for SPKI certificates
32 */
33
34#define _BSD_SOURCE
35
36#include <string.h>
37#include <time.h>
38#include <arpa/inet.h>
39#include <netinet/in.h>
40#include <sys/types.h>
41
42#include "pisa_cert.h"
43
44
45/**
46 * Extract parts of a SPKI certificate.
47 *
48 * @param cert pointer to the certificate text or part of a certificate text
49 * @param name pointer to the pattern we are looking for
50 * @param r pointer to a buffer that the search result will be copied to
51 * @return 0 on success
52 */
53static char *pisa_cert_get_part(char *cert, const char *name, char *r)
54{
55 int level = 0, len = 0;
56 char *p = cert, *start = NULL;
57
58 if (!r) {
59 return NULL;
60 }
61
62 if (!cert) {
63 goto out_err;
64 }
65
66 if (!name) {
67 goto out_err;
68 }
69
70 len = strlen(name);
71 if (len == 0) {
72 goto out_err;
73 }
74
75 while (*p) {
76 if (*p == '(') {
77 level++;
78 if (level == 2 && !strncmp(p + 1, name, len)) {
79 if (*(p + len + 1) == ' ') {
80 start = p++;
81 break;
82 }
83 }
84 }
85 if (*p == ')') {
86 level--;
87 }
88 if (level == 0) {
89 break;
90 }
91 p++;
92 }
93
94 if (!start) {
95 goto out_err;
96 }
97
98 len = 0;
99
100 while (*p) {
101 if (*p == '(') {
102 level++;
103 }
104 if (*p == ')') {
105 level--;
106 if (level == 1) {
107 len = p - start + 1;
108 break;
109 }
110 }
111 if (level == 0) {
112 break;
113 }
114 p++;
115 }
116
117 strncpy(r, start, len);
118 r[len] = '\0';
119
120 return r;
121
122out_err:
123 r[0] = '\0';
124 return NULL;
125}
126
127/**
128 * Get the content from a SPKI certificate part.
129 *
130 * @param cert pointer to the certificate text or part of a certificate text
131 * @param name pointer to the pattern we are looking for
132 * @param r pointer to a buffer that the search result will be copied to
133 * @return 0 on success
134 */
135static void pisa_cert_get_content(char *cert, const char *name, char *r)
136{
137 char *start = cert;
138 int len = 0;
139
140 if (!r) {
141 return;
142 }
143
144 if (!cert || !name || !*name == '(') {
145 goto out_err;
146 }
147
148 if (strlen(name) + 3 > strlen(cert)) {
149 goto out_err;
150 }
151
152 if (strncmp(name, cert + 1, strlen(name))) {
153 goto out_err;
154 }
155 start = cert + strlen(name) + 2;
156
157 if (*start == '\0') {
158 goto out_err;
159 }
160
161 len = strlen(start) - 1;
162 if (*(start + len) != ')') {
163 goto out_err;
164 }
165 strncpy(r, start, len);
166
167out_err:
168 r[len] = '\0';
169}
170
171/**
172 * Splits a certificate into semantic chunks and converts these to
173 * sensible binary representations.
174 *
175 * @param cert the original certificate
176 * @param pc internal representation of the certificate
177 */
178void pisa_split_cert(char *cert, struct pisa_cert *pc)
179{
180 struct tm t;
181 char buffer1[224], buffer2[224];
182 struct in6_addr addr;
183
184 pisa_cert_get_part(cert, "not-before", buffer1);
185 pisa_cert_get_content(buffer1, "not-before", buffer2);
186 strptime(buffer2, "\"%Y-%m-%d_%H:%M:%S\"", &t);
187 pc->not_before = mktime(&t);
188
189 pisa_cert_get_part(cert, "not-after", buffer1);
190 pisa_cert_get_content(buffer1, "not-after", buffer2);
191 strptime(buffer2, "\"%Y-%m-%d_%H:%M:%S\"", &t);
192 pc->not_after = mktime(&t);
193
194 pisa_cert_get_part(cert, "issuer", buffer1);
195 pisa_cert_get_part(buffer1, "hash hit", buffer2);
196 pisa_cert_get_content(buffer2, "hash hit", buffer1);
197 inet_pton(AF_INET6, buffer1, &addr);
198 memcpy(&pc->hit_issuer, &addr, sizeof(struct in6_addr));
199
200 pisa_cert_get_part(cert, "subject", buffer1);
201 pisa_cert_get_part(buffer1, "hash hit", buffer2);
202 pisa_cert_get_content(buffer2, "hash hit", buffer1);
203 inet_pton(AF_INET6, buffer1, &addr);
204 memcpy(&pc->hit_subject, &addr, sizeof(struct in6_addr));
205}
2060
=== removed file 'hipfw/pisa_cert.h'
--- hipfw/pisa_cert.h 2011-11-25 13:52:20 +0000
+++ hipfw/pisa_cert.h 1970-01-01 00:00:00 +0000
@@ -1,47 +0,0 @@
1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef HIPL_HIPFW_PISA_CERT_H
27#define HIPL_HIPFW_PISA_CERT_H
28
29#include <time.h>
30#include <netinet/in.h>
31
32struct pisa_cert {
33 struct in6_addr hit_issuer;
34 struct in6_addr hit_subject;
35 time_t not_before;
36 time_t not_after;
37};
38
39/**
40 * Split the hip_cert_spki_info.cert part into small chunks
41 *
42 * @param cert the hip_cert_spki_info.cert part of the certificate
43 * @param pc datastructure that will contain the chunks
44 */
45void pisa_split_cert(char *cert, struct pisa_cert *pc);
46
47#endif /* HIPL_HIPFW_PISA_CERT_H */
480
=== modified file 'hipfw/rule_management.c'
--- hipfw/rule_management.c 2011-12-15 13:53:03 +0000
+++ hipfw/rule_management.c 2012-03-09 12:45:28 +0000
@@ -68,6 +68,7 @@
68#define IN_IF_STR "-i"68#define IN_IF_STR "-i"
69#define OUT_IF_STR "-o"69#define OUT_IF_STR "-o"
70#define STATE_STR "-state"70#define STATE_STR "-state"
71#define CERT_STR "-cert"
71#define SRC_HI_STR "--hi"72#define SRC_HI_STR "--hi"
72#define VERIFY_RESPONDER_STR "--verify_responder"73#define VERIFY_RESPONDER_STR "--verify_responder"
73#define ACCEPT_MOBILE_STR "--accept_mobile"74#define ACCEPT_MOBILE_STR "--accept_mobile"
@@ -97,6 +98,7 @@
97 STATE_OPTION,98 STATE_OPTION,
98 IN_IF_OPTION,99 IN_IF_OPTION,
99 OUT_IF_OPTION,100 OUT_IF_OPTION,
101 CERT_OPTION,
100 HOOK102 HOOK
101};103};
102104
@@ -248,6 +250,7 @@
248 rule->state = NULL;250 rule->state = NULL;
249 rule->in_if = NULL;251 rule->in_if = NULL;
250 rule->out_if = NULL;252 rule->out_if = NULL;
253 rule->cert = NULL;
251 rule->hook = -1;254 rule->hook = -1;
252 rule->accept = -1;255 rule->accept = -1;
253 return rule;256 return rule;
@@ -283,6 +286,7 @@
283 free(rule->state);286 free(rule->state);
284 free_string_option(rule->in_if);287 free_string_option(rule->in_if);
285 free_string_option(rule->out_if);288 free_string_option(rule->out_if);
289 free_string_option(rule->cert);
286 free(rule);290 free(rule);
287 }291 }
288}292}
@@ -682,6 +686,15 @@
682 return NULL;686 return NULL;
683 }687 }
684 option_found = STATE_OPTION;688 option_found = STATE_OPTION;
689 } else if (!strcmp(token, CERT_STR)) {
690 /* option already defined */
691 /* rule only applicable to forward hook */
692 if (rule->cert != NULL || rule->hook != NF_IP6_FORWARD) {
693 HIP_DEBUG("error parsing rule: cert option \n");
694 free_rule(rule);
695 return NULL;
696 }
697 option_found = CERT_OPTION;
685 } else if (!strcmp(token, VERIFY_RESPONDER_STR)) {698 } else if (!strcmp(token, VERIFY_RESPONDER_STR)) {
686 /* related state option must be defined */699 /* related state option must be defined */
687 if (rule->state == NULL) {700 if (rule->state == NULL) {
@@ -794,6 +807,16 @@
794 return NULL;807 return NULL;
795 }808 }
796 option_found = NO_OPTION;809 option_found = NO_OPTION;
810 } else if (option_found == CERT_OPTION) {
811 rule->cert = malloc(sizeof(struct string_option));
812 rule->cert->value = strdup(token);
813 rule->cert->boolean = 0;
814 if (rule->cert == NULL || rule->cert->value == NULL) {
815 HIP_DEBUG("error parsing rule: cert value \n");
816 free_rule(rule);
817 return NULL;
818 }
819 option_found = NO_OPTION;
797 } else if (option_found == IN_IF_OPTION) {820 } else if (option_found == IN_IF_OPTION) {
798 rule->in_if = parse_if(token);821 rule->in_if = parse_if(token);
799 if (rule->in_if == NULL) {822 if (rule->in_if == NULL) {
800823
=== modified file 'hipfw/rule_management.h'
--- hipfw/rule_management.h 2011-11-25 13:52:20 +0000
+++ hipfw/rule_management.h 2012-03-09 12:45:28 +0000
@@ -76,6 +76,7 @@
76 struct hip_host_id *src_hi;76 struct hip_host_id *src_hi;
77 struct int_option *type;77 struct int_option *type;
78 struct state_option *state;78 struct state_option *state;
79 struct string_option *cert;
79 struct string_option *in_if;80 struct string_option *in_if;
80 struct string_option *out_if;81 struct string_option *out_if;
81 unsigned int hook;82 unsigned int hook;
8283
=== modified file 'lib/core/builder.c'
--- lib/core/builder.c 2012-03-08 13:39:18 +0000
+++ lib/core/builder.c 2012-03-09 12:45:28 +0000
@@ -1118,6 +1118,10 @@
1118 case HIP_MSG_REINIT_FULLRELAY: return "HIP_MSG_REINIT_FULLRELAY";1118 case HIP_MSG_REINIT_FULLRELAY: return "HIP_MSG_REINIT_FULLRELAY";
1119 case HIP_MSG_FIREWALL_START: return "HIP_MSG_FIREWALL_START";1119 case HIP_MSG_FIREWALL_START: return "HIP_MSG_FIREWALL_START";
1120 case HIP_MSG_MANUAL_UPDATE_PACKET: return "HIP_MSG_MANUAL_UPDATE_PACKET";1120 case HIP_MSG_MANUAL_UPDATE_PACKET: return "HIP_MSG_MANUAL_UPDATE_PACKET";
1121 case HIP_MSG_CERT_SPKI_SIGN: return "HIP_MSG_CERT_SPKI_SIGN";
1122 case HIP_MSG_CERT_SPKI_VERIFY: return "HIP_MSG_CERT_SPKI_VERIFY";
1123 case HIP_MSG_CERT_X509V3_SIGN: return "HIP_MSG_CERT_X509V3_SIGN";
1124 case HIP_MSG_CERT_X509V3_VERIFY: return "HIP_MSG_CERT_X509V3_VERIFY";
1121 default:1125 default:
1122 return lmod_get_packet_identifier(msg_type);1126 return lmod_get_packet_identifier(msg_type);
1123 }1127 }
@@ -1137,6 +1141,8 @@
1137 switch (param_type) {1141 switch (param_type) {
1138 case HIP_PARAM_ACK: return "HIP_PARAM_ACK";1142 case HIP_PARAM_ACK: return "HIP_PARAM_ACK";
1139 case HIP_PARAM_CERT: return "HIP_PARAM_CERT";1143 case HIP_PARAM_CERT: return "HIP_PARAM_CERT";
1144 case HIP_PARAM_CERT_X509_REQ: return "HIP_PARAM_CERT_X509_REQ";
1145 case HIP_PARAM_CERT_X509_RESP: return "HIP_PARAM_CERT_X509_RESP";
1140 case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY";1146 case HIP_PARAM_DH_SHARED_KEY: return "HIP_PARAM_DH_SHARED_KEY";
1141 case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN";1147 case HIP_PARAM_DIFFIE_HELLMAN: return "HIP_PARAM_DIFFIE_HELLMAN";
1142 case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA";1148 case HIP_PARAM_DSA_SIGN_DATA: return "HIP_PARAM_DSA_SIGN_DATA";
@@ -3265,7 +3271,8 @@
3265 * @return zero on success or negative on failure3271 * @return zero on success or negative on failure
3266 */3272 */
3267int hip_build_param_cert(struct hip_common *msg, uint8_t group, uint8_t count,3273int hip_build_param_cert(struct hip_common *msg, uint8_t group, uint8_t count,
3268 uint8_t id, uint8_t type, void *data, size_t size)3274 uint8_t id, enum hip_cert_type type, void *data,
3275 size_t size)
3269{3276{
3270 struct hip_cert cert;3277 struct hip_cert cert;
32713278
@@ -3352,7 +3359,7 @@
3352}3359}
33533360
3354/**3361/**
3355 * Build and append a X509 certiticate request parameter into a HIP control3362 * Build and append a X509 certificate request parameter into a HIP control
3356 * message (on-the-wire)3363 * message (on-the-wire)
3357 *3364 *
3358 * @param msg a pointer to the message where the parameter will be3365 * @param msg a pointer to the message where the parameter will be
@@ -3361,7 +3368,7 @@
3361 * @return zero on success, or negative on failure3368 * @return zero on success, or negative on failure
3362 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>3369 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
3363 */3370 */
3364int hip_build_param_cert_x509_req(struct hip_common *msg, struct in6_addr *addr)3371int hip_build_param_cert_x509_req(struct hip_common *msg, hip_hit_t *addr)
3365{3372{
3366 struct hip_cert_x509_req subj;3373 struct hip_cert_x509_req subj;
33673374
@@ -3399,7 +3406,7 @@
3399 * @return zero on success, or negative on failure3406 * @return zero on success, or negative on failure
3400 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>3407 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
3401 */3408 */
3402int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der, int len)3409int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der, unsigned len)
3403{3410{
3404 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_RESP);3411 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_RESP);
3405}3412}
@@ -3415,7 +3422,7 @@
3415 * @return zero on success, or negative on failure3422 * @return zero on success, or negative on failure
3416 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>3423 * @see <a href="http://tools.ietf.org/html/draft-ietf-hip-cert">draft-ietf-hip-cert</a>
3417 */3424 */
3418int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, int len)3425int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der, unsigned len)
3419{3426{
3420 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_REQ);3427 return build_param_cert_x509(msg, der, len, HIP_PARAM_CERT_X509_REQ);
3421}3428}
34223429
=== modified file 'lib/core/builder.h'
--- lib/core/builder.h 2012-02-23 10:43:16 +0000
+++ lib/core/builder.h 2012-03-09 12:45:28 +0000
@@ -115,13 +115,9 @@
115 uint32_t,115 uint32_t,
116 uint16_t,116 uint16_t,
117 struct hip_crypto_key *);117 struct hip_crypto_key *);
118int hip_build_param_cert(struct hip_common *,118int hip_build_param_cert(struct hip_common *msg, uint8_t group, uint8_t count,
119 uint8_t,119 uint8_t id, enum hip_cert_type type, void *data,
120 uint8_t,120 size_t size);
121 uint8_t,
122 uint8_t,
123 void *,
124 size_t);
125int hip_build_param_puzzle(struct hip_common *const msg,121int hip_build_param_puzzle(struct hip_common *const msg,
126 const uint8_t val_K,122 const uint8_t val_K,
127 const uint8_t lifetime,123 const uint8_t lifetime,
@@ -159,8 +155,10 @@
159int hip_build_param_cert_spki_info(struct hip_common *msg,155int hip_build_param_cert_spki_info(struct hip_common *msg,
160 struct hip_cert_spki_info *cert_info);156 struct hip_cert_spki_info *cert_info);
161int hip_build_param_cert_x509_req(struct hip_common *, struct in6_addr *);157int hip_build_param_cert_x509_req(struct hip_common *, struct in6_addr *);
162int hip_build_param_cert_x509_resp(struct hip_common *, char *, int);158int hip_build_param_cert_x509_resp(struct hip_common *msg, char *der,
163int hip_build_param_cert_x509_ver(struct hip_common *, char *, int);159 unsigned len);
160int hip_build_param_cert_x509_ver(struct hip_common *msg, char *der,
161 unsigned len);
164162
165int hip_build_param_hit_to_ip_set(struct hip_common *, const char *);163int hip_build_param_hit_to_ip_set(struct hip_common *, const char *);
166int hip_build_user_hdr(struct hip_common *, hip_hdr, hip_hdr_err);164int hip_build_user_hdr(struct hip_common *, hip_hdr, hip_hdr_err);
167165
=== added file 'lib/core/cert.c'
--- lib/core/cert.c 1970-01-01 00:00:00 +0000
+++ lib/core/cert.c 2012-03-09 12:45:28 +0000
@@ -0,0 +1,286 @@
1/*
2 * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26/**
27 * @file
28 * @brief functionality for handling X509 certificates
29 */
30
31#include <errno.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
35#include <unistd.h>
36#include <openssl/x509.h>
37#include <openssl/pem.h>
38
39#include "builder.h"
40#include "debug.h"
41#include "ife.h"
42#include "common.h"
43#include "cert.h"
44
45/**
46 * This function encodes the given certificate to its DER encoding for
47 * transmission over the wire. The encoded certificate is written to @p buf.
48 *
49 * @param cert the certificate to encode
50 * @param buf the output is written here
51 *
52 * @return the length of the encoded data
53 *
54 * @note: The encoded data is in binary form and may contain embedded zeroes.
55 * Functions such as strlen() will not return the correct length of the
56 * encoded structure. Therefore the length value returned by this
57 * function should always be used.
58 */
59int cert_X509_to_DER(X509 *const cert, unsigned char **buf)
60{
61 int len;
62
63 if (!cert) {
64 HIP_ERROR("Cannot encode NULL-certificate\n");
65 return -1;
66 }
67 if (!buf) {
68 HIP_ERROR("Cannot create output buffer at NULL-pointer.\n");
69 return -1;
70 }
71
72 *buf = NULL;
73 len = i2d_X509(cert, buf);
74
75 if (len < 0) {
76 HIP_ERROR("Could not DER-encode the given certificate.\n");
77 return -1;
78 }
79 return len;
80}
81
82/**
83 * Function to decode a DER-encoded certificate to the internal OpenSSL X509
84 * structure.
85 *
86 * @param buf the buffer from which the DER-encoded certificate is read
87 * @param len the length of the DER-encoded certificate
88 * (NOTE: strlen() and similar functions fail, since DER is
89 * basically binary data that can contain 0-bytes).
90 *
91 * @return the OpenSSL X509 structure corresponding the DER-encoded
92 * certificate, NULL if errors occured
93 */
94X509 *cert_DER_to_X509(const unsigned char *buf, const int len)
95{
96 if (!buf) {
97 HIP_ERROR("Cannot decode from NULL-buffer\n");
98 return NULL;
99 }
100 if (len <= 0) {
101 HIP_ERROR("Cannot decode certificate of length <= 0\n");
102 return NULL;
103 }
104 return d2i_X509(NULL, &buf, len);
105}
106
107/**
108 * Load a X509 certificate from @p file. If @p file contains more
109 * than one certificate, the certificate at the top of the file is
110 * returned.
111 *
112 * @param file the file to load the certficate from
113 * @param fmt the input format of the certificate
114 *
115 * @return a pointer to an X.509 certificate on success, NULL on error
116 */
117X509 *cert_load_x509_certificate(const char *const file,
118 enum encoding_format fmt)
119{
120 FILE *fp = NULL;
121 X509 *cert = NULL;
122
123 if (!file) {
124 HIP_ERROR("Cannot read certificate from NULL-filename.\n");
125 return NULL;
126 }
127
128 fp = fopen(file, "rb");
129 if (!fp) {
130 HIP_ERROR("Could not open file for reading: %s\n", file);
131 return NULL;
132 }
133
134 if (fmt == ENCODING_FORMAT_PEM) {
135 cert = PEM_read_X509(fp, NULL, NULL, NULL);
136 } else if (fmt == ENCODING_FORMAT_DER) {
137 cert = d2i_X509_fp(fp, NULL);
138 } else {
139 HIP_ERROR("Invalid encoding format %i \n", fmt);
140 return NULL;
141 }
142
143 if (fclose(fp)) {
144 HIP_ERROR("Error closing file: %s\n", file);
145 X509_free(cert);
146 return NULL;
147 } else if (!cert) {
148 HIP_ERROR("Could not decode certificate from file.\n");
149 return NULL;
150 }
151
152 return cert;
153}
154
155/**
156 * Search for hip_cert parameter in @p msg and try to decode the data in
157 * the first certificate parameter of a X509 certificate.
158 *
159 * @param msg the message to extract the certificate from
160 *
161 * @return the first X509 certificate found in the message on success,
162 * NULL on error and if no certificates were found
163 */
164X509 *cert_get_X509_from_msg(const struct hip_common *const msg)
165{
166 const struct hip_cert *param_cert = NULL;
167
168 if (!(param_cert = hip_get_param(msg, HIP_PARAM_CERT))) {
169 HIP_ERROR("Message contains no certificate.\n");
170 return NULL;
171 }
172
173 /* The contents of the certificate begin after the header of the
174 * hip_cert parameter. */
175 return cert_DER_to_X509((const unsigned char *) (param_cert + 1),
176 ntohs(param_cert->length) -
177 sizeof(struct hip_cert) +
178 sizeof(struct hip_tlv_common));
179}
180
181/**
182 * Compare a given public key @p pkey with the public key
183 * contained in @p cert.
184 *
185 * @param cert the X509 certificate
186 * @param pkey the public key to match
187 *
188 * @return 1 if match, 0 otherwise
189 */
190int cert_match_public_key(X509 *cert, const EVP_PKEY *pkey)
191{
192 EVP_PKEY *pkey2 = NULL;
193
194 if (!cert || !pkey) {
195 return 0;
196 }
197 pkey2 = X509_get_pubkey(cert);
198 return EVP_PKEY_cmp(pkey2, pkey);
199}
200
201/**
202 * Build and verify a certificate chain.
203 *
204 * @param leaf_cert the certificate to verify
205 * @param trusted_lookup_dir certificates in this directory are used as
206 * root certificates
207 * @param trusted_chain a certificate stack that can contain additional
208 * trusted certificates
209 * @param untrusted_chain a chain of untrusted certificates that can be
210 * used to build a complete certificate chain
211 *
212 * @return 0 if a certificate chain could be built and
213 * verified, a non-zero error code otherwise
214 */
215int cert_verify_chain(X509 *leaf_cert,
216 const char *trusted_lookup_dir,
217 STACK_OF(X509) *trusted_chain,
218 STACK_OF(X509) *untrusted_chain)
219{
220 int err = 0;
221 X509_LOOKUP *lookup = NULL;
222 X509_STORE *verify_ctx_store = NULL;
223 X509_STORE_CTX *verify_ctx = NULL;
224
225 if (!leaf_cert) {
226 HIP_ERROR("Cannot verify NULL-certificate.\n");
227 return -1;
228 }
229
230 if (!trusted_lookup_dir && !trusted_chain) {
231 HIP_ERROR("Need trusted dir and trusted chain.\n");
232 return -1;
233 }
234
235 /* Build the verify context */
236 if (!(verify_ctx_store = X509_STORE_new())) {
237 HIP_ERROR("Failed to init certificate store.\n");
238 return -1;
239 }
240 if (!(lookup = X509_STORE_add_lookup(verify_ctx_store, X509_LOOKUP_hash_dir()))) {
241 HIP_ERROR("Failed to init lookup directory.\n");
242 return -1;
243 }
244 if (trusted_lookup_dir) {
245 if (!X509_LOOKUP_add_dir(lookup, trusted_lookup_dir,
246 X509_FILETYPE_PEM)) {
247 HIP_ERROR("Failed to add directory %s to trusted lookup resources.\n",
248 trusted_lookup_dir);
249 return -1;
250 }
251 } else {
252 X509_LOOKUP_add_dir(lookup, NULL, X509_FILETYPE_DEFAULT);
253 }
254
255 if (!(verify_ctx = X509_STORE_CTX_new())) {
256 HIP_ERROR("Failed to allocate new verify context.\n");
257 return -ENOMEM;
258 }
259 if (!X509_STORE_CTX_init(verify_ctx, verify_ctx_store, leaf_cert,
260 untrusted_chain)) {
261 HIP_ERROR("Failed to setup verify context.\n");
262 X509_STORE_CTX_free(verify_ctx);
263 return -1;
264 }
265 if (trusted_chain) {
266 X509_STORE_CTX_trusted_stack(verify_ctx, trusted_chain);
267 }
268
269 /* Finally do the verification and output some info on error */
270 OpenSSL_add_all_algorithms();
271 err = X509_verify_cert(verify_ctx);
272
273 if (err != 1) {
274 err = X509_STORE_CTX_get_error(verify_ctx);
275 HIP_DEBUG("X509 verify cert error: %d \n", err);
276 HIP_DEBUG("at depth: %d \n", X509_STORE_CTX_get_error_depth(verify_ctx));
277 HIP_DEBUG("reason: %s\n", X509_verify_cert_error_string(err));
278 HIP_DEBUG("certificate:\n");
279 X509_print_fp(stderr, X509_STORE_CTX_get_current_cert(verify_ctx));
280 } else {
281 err = 0;
282 }
283
284 X509_STORE_CTX_free(verify_ctx);
285 return err;
286}
0287
=== added file 'lib/core/cert.h'
--- lib/core/cert.h 1970-01-01 00:00:00 +0000
+++ lib/core/cert.h 2012-03-09 12:45:28 +0000
@@ -0,0 +1,51 @@
1/*
2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#ifndef HIPL_LIB_CORE_CERT_H
27#define HIPL_LIB_CORE_CERT_H
28
29#include <openssl/x509.h>
30
31#include "lib/core/protodefs.h"
32
33enum encoding_format {
34 ENCODING_FORMAT_PEM,
35 ENCODING_FORMAT_DER
36};
37
38int cert_X509_to_DER(X509 *const cert, unsigned char **buf);
39X509 *cert_DER_to_X509(const unsigned char *const buf, const int len);
40
41X509 *cert_load_x509_certificate(const char *const file,
42 enum encoding_format fmt);
43X509 *cert_get_X509_from_msg(const struct hip_common *const msg);
44
45int cert_match_public_key(X509 *cert, const EVP_PKEY *pkey);
46int cert_verify_chain(X509 *leaf_cert,
47 const char *trusted_lookup_dir,
48 STACK_OF(X509) *trusted_chain,
49 STACK_OF(X509) *untrusted_chain);
50
51#endif /* HIPL_LIB_CORE_CERT_H */
052
=== modified file 'lib/core/certtools.c'
--- lib/core/certtools.c 2012-01-14 15:29:47 +0000
+++ lib/core/certtools.c 2012-03-09 12:45:28 +0000
@@ -710,8 +710,8 @@
710 /* get the struct from the message sent back by the daemon */710 /* get the struct from the message sent back by the daemon */
711 HIP_IFEL(!(p = hip_get_param(msg, HIP_PARAM_CERT_X509_RESP)), -1,711 HIP_IFEL(!(p = hip_get_param(msg, HIP_PARAM_CERT_X509_RESP)), -1,
712 "No name x509 struct found\n");712 "No name x509 struct found\n");
713 memcpy(certificate, p->der, p->der_len);713 memcpy(certificate, p->der, ntohl(p->der_len));
714 err = p->der_len;714 err = ntohl(p->der_len);
715715
716out_err:716out_err:
717 free(msg);717 free(msg);
@@ -797,18 +797,18 @@
797}797}
798798
799/**799/**
800 * Load a configuration file from HIP_CERT_CONF_PATH.800 * Load the indicated configuration file.
801 *801 *
802 * @return CONF pointer if OK, NULL on error802 * @return CONF pointer if OK, NULL on error
803 */803 */
804CONF *hip_open_conf(const char *filename)804CONF *hip_open_conf(const char *filename)
805{805{
806 long err;
807 CONF *conf;806 CONF *conf;
808807
809 conf = NCONF_new(NCONF_default());808 conf = NCONF_new(NCONF_default());
810 if (!NCONF_load(conf, filename, &err)) {809 if (!NCONF_load(conf, filename, NULL)) {
811 HIP_ERROR("Error opening the configuration file");810 HIP_ERROR("Error opening the configuration file");
811 NCONF_free(conf);
812 return NULL;812 return NULL;
813 }813 }
814 return conf;814 return conf;
815815
=== modified file 'lib/core/conf.c'
--- lib/core/conf.c 2012-01-13 16:25:15 +0000
+++ lib/core/conf.c 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -59,10 +59,12 @@
59#include <sys/ioctl.h>59#include <sys/ioctl.h>
60#include <sys/socket.h>60#include <sys/socket.h>
61#include <sys/types.h>61#include <sys/types.h>
62#include <openssl/pem.h>
6263
63#include "common.h"
64#include "config.h"64#include "config.h"
65#include "builder.h"65#include "builder.h"
66#include "cert.h"
67#include "common.h"
66#include "crypto.h"68#include "crypto.h"
67#include "debug.h"69#include "debug.h"
68#include "hostid.h"70#include "hostid.h"
@@ -126,7 +128,8 @@
126/* unused, was ACTION_HANDOVER 39 */128/* unused, was ACTION_HANDOVER 39 */
127#define ACTION_MANUAL_UPDATE 40129#define ACTION_MANUAL_UPDATE 40
128#define ACTION_BROADCAST 41130#define ACTION_BROADCAST 41
129#define ACTION_MAX 42 /* exclusive */131#define ACTION_ACQUIRE 42
132#define ACTION_MAX 43 /* exclusive */
130133
131/**134/**
132 * TYPE_ constant list, as an index for each action_handler function.135 * TYPE_ constant list, as an index for each action_handler function.
@@ -176,7 +179,8 @@
176/* unused, was TYPE_HANDOVER 42 */179/* unused, was TYPE_HANDOVER 42 */
177#define TYPE_MANUAL_UPDATE 43180#define TYPE_MANUAL_UPDATE 43
178#define TYPE_BROADCAST 44181#define TYPE_BROADCAST 44
179#define TYPE_MAX 45 /* exclusive */182#define TYPE_CERTIFICATE 45
183#define TYPE_MAX 46 /* exclusive */
180184
181/* #define TYPE_RELAY 22 */185/* #define TYPE_RELAY 22 */
182186
@@ -230,6 +234,7 @@
230 "shotgun on|off\n"234 "shotgun on|off\n"
231 "id-to-addr hit|lsi\n"235 "id-to-addr hit|lsi\n"
232 "broadcast on|off\n"236 "broadcast on|off\n"
237 "acquire certificate <hit> [valid-till_timestamp]\n"
233;238;
234239
235/**240/**
@@ -648,6 +653,8 @@
648 }653 }
649 } else if (!strcmp("broadcast", argv[2])) {654 } else if (!strcmp("broadcast", argv[2])) {
650 ret = ACTION_BROADCAST;655 ret = ACTION_BROADCAST;
656 } else if (!strcmp("acquire", argv[2])) {
657 ret = ACTION_ACQUIRE;
651 }658 }
652659
653 return ret;660 return ret;
@@ -698,6 +705,7 @@
698 case ACTION_TRANSORDER:705 case ACTION_TRANSORDER:
699 case ACTION_NAT_LOCAL_PORT:706 case ACTION_NAT_LOCAL_PORT:
700 case ACTION_NAT_PEER_PORT:707 case ACTION_NAT_PEER_PORT:
708 case ACTION_ACQUIRE:
701 count = 2;709 count = 2;
702 break;710 break;
703 default:711 default:
@@ -750,6 +758,8 @@
750 } else {758 } else {
751 ret = TYPE_NAT;759 ret = TYPE_NAT;
752 }760 }
761 } else if (!strcmp("certificate", text)) {
762 ret = TYPE_CERTIFICATE;
753 } else if (strcmp("locator", argv[2]) == 0) {763 } else if (strcmp("locator", argv[2]) == 0) {
754 ret = TYPE_LOCATOR;764 ret = TYPE_LOCATOR;
755 } else if (!strcmp("debug", text)) {765 } else if (!strcmp("debug", text)) {
@@ -819,6 +829,7 @@
819 case ACTION_HIT_TO_IP:829 case ACTION_HIT_TO_IP:
820 case ACTION_HIT_TO_IP_SET:830 case ACTION_HIT_TO_IP_SET:
821 case ACTION_BROADCAST:831 case ACTION_BROADCAST:
832 case ACTION_ACQUIRE:
822 type_arg = 3;833 type_arg = 3;
823 break;834 break;
824 case ACTION_MANUAL_UPDATE:835 case ACTION_MANUAL_UPDATE:
@@ -2424,6 +2435,122 @@
2424}2435}
24252436
2426/**2437/**
2438 * Utility function which compactly checks whether a string represents
2439 * a positive natural number, since scanf() is too lenient.
2440 *
2441 * @param string NULL-terminated string to be checked
2442 *
2443 * @return 1 if the only characters in the string are digits,
2444 * optionally with one leading '+' sign; 0 otherwise
2445 */
2446static int is_pos_natural_number(const char *string)
2447{
2448 if (string) {
2449 size_t len;
2450
2451 // allow one leading '+'
2452 if (string[0] == '+') {
2453 string++;
2454 }
2455
2456 if ((len = strlen(string)) > 0) {
2457 for (size_t i = 0; i < len; i++) {
2458 if (string[i] < '0' || string[i] > '9') {
2459 return 0;
2460 }
2461 }
2462 return 1;
2463 }
2464 }
2465 return 0;
2466}
2467
2468static int conf_handle_certificate(struct hip_common *msg,
2469 int action,
2470 const char *opt[],
2471 int optc,
2472 UNUSED int send_only)
2473{
2474 hip_hit_t subject_hit;
2475 uint32_t valid_until_h = 0, valid_until_n = 0;
2476 int scanf_res = 0, err = 0;
2477 X509 *cert = NULL;
2478 const struct hip_cert_x509_resp *p = NULL;
2479
2480 /* Convert the parameter strings input by the user into the
2481 * appropriate binary formats for further processing. */
2482 const int pton_res = inet_pton(AF_INET6, opt[0], &subject_hit);
2483
2484 if (optc == 2 && is_pos_natural_number(opt[1])) {
2485 /* Need to use sscanf() here: strtol() won't do since we want the result
2486 * of the conversion to fit into an uint32_t, whereas strtol() and
2487 * relatives would write to a variable of platform-dependent size. */
2488 scanf_res = sscanf(opt[1], "%" SCNu32, &valid_until_h);
2489 }
2490
2491 /* The second parameter after "acquire certificate" is optional, so we
2492 * accept optc == 1 as well as optc == 2 (the latter is implied if
2493 * scanf_res is 1). */
2494 if (pton_res == 1 && action == ACTION_ACQUIRE &&
2495 (optc == 1 || scanf_res == 1)) {
2496 HIP_DEBUG_HIT("Requesting certificate for subject", &subject_hit);
2497
2498 if (hip_build_user_hdr(msg, HIP_MSG_CERT_X509V3_SIGN, 0)) {
2499 HIP_ERROR("Failed to build user message header.\n");
2500 return -1;
2501 }
2502
2503 /* If the user provides a second parameter (following the HIT), it is
2504 * meant to indicate the point in time when validity of the issued
2505 * certificate ends; expressed in "number of seconds since the epoch";
2506 * we use a uint32_t for this, so we're creating a year-2106-problem
2507 * here (be scared). */
2508 if (scanf_res == 1) {
2509 valid_until_n = htonl(valid_until_h);
2510 if (hip_build_param_contents(msg, &valid_until_n,
2511 HIP_PARAM_UINT, sizeof(uint32_t))) {
2512 HIP_ERROR("Failed to build validity parameter.\n");
2513 return -1;
2514 }
2515 }
2516
2517 if (hip_build_param_cert_x509_req(msg, &subject_hit)) {
2518 HIP_ERROR("Failed to build cert_x509_req parameter.\n");
2519 return -1;
2520 }
2521 } else {
2522 err = -1;
2523 HIP_ERROR("Invalid arguments.\n");
2524 }
2525
2526 /* Send the message to the daemon. The daemon fills the message. */
2527 if (hip_send_recv_daemon_info(msg, send_only, 0)) {
2528 return -ECOMM;
2529 }
2530
2531 /* Handle the answer */
2532 if (!(p = hip_get_param(msg, HIP_PARAM_CERT_X509_RESP))) {
2533 HIP_ERROR("No name x509 struct found\n");
2534 return -1;
2535 }
2536 const uint32_t der_len_h = ntohl(p->der_len);
2537 if (!(cert = cert_DER_to_X509(p->der, der_len_h))) {
2538 HIP_ERROR("Could not get X509 certificate from DER encoding\n.");
2539 return -1;
2540 }
2541 if (fwrite(p->der, der_len_h, 1, stdout) != 1) {
2542 HIP_ERROR("Couldn't output certificate.\n");
2543 return -1;
2544 }
2545
2546 /* Clear the msg (and in particular its message type field)
2547 * to prevent hip_do_hipconf() from sending it again. */
2548 hip_msg_init(msg);
2549
2550 return err;
2551}
2552
2553/**
2427 * Function pointer array containing pointers to handler functions.2554 * Function pointer array containing pointers to handler functions.
2428 * Add a handler function for your new action in the action_handler[] array.2555 * Add a handler function for your new action in the action_handler[] array.
2429 * If you added a handler function here, do not forget to define that function2556 * If you added a handler function here, do not forget to define that function
@@ -2492,6 +2619,7 @@
2492 NULL, /* 42: unused, was TYPE_HANDOVER */2619 NULL, /* 42: unused, was TYPE_HANDOVER */
2493 conf_handle_manual_update, /* 43: TYPE_MANUAL_UPDATE */2620 conf_handle_manual_update, /* 43: TYPE_MANUAL_UPDATE */
2494 conf_handle_broadcast, /* 44: TYPE_BROADCAST */2621 conf_handle_broadcast, /* 44: TYPE_BROADCAST */
2622 conf_handle_certificate, /* 45: TYPE_CERTIFICATE */
2495 NULL /* TYPE_MAX, the end. */2623 NULL /* TYPE_MAX, the end. */
2496};2624};
24972625
24982626
=== modified file 'lib/core/protodefs.h'
--- lib/core/protodefs.h 2012-03-08 18:50:52 +0000
+++ lib/core/protodefs.h 2012-03-09 12:45:28 +0000
@@ -375,6 +375,20 @@
375#define HIP_VER_RES 0x01 /* Version 1, reserved 0 */375#define HIP_VER_RES 0x01 /* Version 1, reserved 0 */
376#define HIP_USER_VER_RES 0xF0 /* Internal messages */376#define HIP_USER_VER_RES 0xF0 /* Internal messages */
377377
378
379/* HIP certificate types
380 * (according to RFC 6253) */
381enum hip_cert_type {
382 HIP_CERT_X509V3,
383 HIP_CERT_SPKI,
384 HIP_CERT_X509V3_HASH_URL,
385 HIP_CERT_SPKI_HASH_URL,
386 HIP_CERT_X509V3_LDAP_URL,
387 HIP_CERT_SPKI_LDAP_URL,
388 HIP_CERT_X509V3_DN,
389 HIP_CERT_SPKI_DN,
390};
391
378/**392/**
379 * @defgroup hip_ha_controls HIP host association controls393 * @defgroup hip_ha_controls HIP host association controls
380 *394 *
381395
=== added directory 'modules/cert'
=== added directory 'modules/cert/hipd'
=== renamed file 'hipd/pisa.c' => 'modules/cert/hipd/cert.c'
--- hipd/pisa.c 2011-10-25 21:14:16 +0000
+++ modules/cert/hipd/cert.c 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2012 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -25,59 +25,179 @@
2525
26/**26/**
27 * @file27 * @file
28 * This file contains functions that are specific to PISA. They deal with the28 * @brief functions to add certificates to R2 and U2 messages
29 * certificate loading.
30 *
31 * @brief Functions for certificate loading
32 */29 */
3330
31#include <stdbool.h>
34#include <stdio.h>32#include <stdio.h>
35#include <stdlib.h>33#include <stdlib.h>
36#include <string.h>34#include <string.h>
3735
38#include "config.h"36#include "hipd/hipd.h"
37#include "hipd/pkt_handling.h"
38#include "lib/core/builder.h"
39#include "lib/core/cert.h"
39#include "lib/core/debug.h"40#include "lib/core/debug.h"
40#include "hipd.h"41#include "lib/core/ife.h"
41#include "pisa.h"42#include "lib/core/protodefs.h"
4243#include "modules/midauth/hipd/midauth.h"
43#define CERT_MAX_SIZE 102444#include "modules/update/hipd/update.h"
4445#include "cert.h"
45static char *midauth_cert = NULL;46
4647static X509 *host_cert = NULL;
47/**48
48 * Load a certificate from the file HIPL_SYSCONFDIR/cert and store it in memory49/**
49 *50 * Handler that adds the certificate to an R2 message.
50 * @return 0 on success51 *
51 */52 * @param msg the message where to add the certificate
52static int pisa_load_certificate(void)53 * @param certificate the certificate to add to the message
53{54 *
54 FILE *f = NULL;55 * @return 0 on success, negative on error
5556 */
56 free(midauth_cert);57static int hip_add_certificate(struct hip_common *msg, X509 *certificate)
57 midauth_cert = calloc(1, CERT_MAX_SIZE);58{
5859 unsigned char *buf;
59 if (!(f = fopen(HIPL_SYSCONFDIR "/cert", "r"))) {60 int len = 0;
60 HIP_ERROR("Could not open certificate file.\n");61
61 return -1;62 /* Sanity checks */
62 }63 if (!msg) {
6364 HIP_ERROR("Message is NULL\n");
64 if (fread(midauth_cert, CERT_MAX_SIZE - 1, 1, f) == 0) {65 return -1;
65 perror("fread returned 0");66 }
66 }67 if (!certificate) {
67 fclose(f);68 HIP_ERROR("Certificate is NULL\n");
68 return 0;69 return -1;
69}70 }
7071
71/**72 /* Encode the certificate to DER and build the certificate parameter. */
72 * Load a certificate from disk and return a pointer to the global73 if ((len = cert_X509_to_DER(certificate, &buf)) < 0) {
73 * variable containing it.74 HIP_ERROR("Encoding error\n");
74 *75 return -1;
75 * @see pisa_load_certificate*76 }
76 *77 if (hip_build_param_cert(msg, 0, 1, 1, HIP_CERT_X509V3, buf, len)) {
77 * @return pointer to midauth_cert78 HIP_ERROR("Building of certificate parameter failed.\n");
78 */79 return -1;
79char *hip_pisa_get_certificate(void)80 }
80{81
81 pisa_load_certificate();82 return 0;
82 return midauth_cert;83}
84
85/**
86 * Handler that adds the certificate to an R2 message.
87 *
88 * @param packet_type unused
89 * @param ha_state unused
90 * @param ctx the packet context
91 *
92 * @return 0 on success, negative on failure
93 *
94 * @note: The certificate is regarded non-critical thus the function does
95 * not fail even if no certificate is available.
96 */
97static int hip_add_certificate_r2(UNUSED const uint8_t packet_type,
98 UNUSED const uint32_t ha_state,
99 struct hip_packet_context *ctx)
100{
101 if (hip_add_certificate(ctx->output_msg, host_cert)) {
102 HIP_DEBUG("Sending R2 without certificate.\n");
103 }
104 return 0;
105}
106
107/**
108 * Handler that adds the certificate to the second or third update message.
109 * A certificate should only be included if the previous
110 * update packet contained a middlebox challenge.
111 *
112 * @param packet_type unused
113 * @param ha_state unused
114 * @param ctx the packet context
115 *
116 * @return 0 on success, negative on failure
117 *
118 * @note: The certificate is regarded non-critical thus the function does
119 * not fail even if no certificate is available.
120 */
121static int hip_add_certificate_update(UNUSED const uint8_t packet_type,
122 UNUSED const uint32_t ha_state,
123 struct hip_packet_context *ctx)
124{
125 if (!host_cert) {
126 HIP_DEBUG("No certificate available.\n");
127 return 0;
128 }
129
130 /* Include a certificate in the U2 or U3, if available. */
131 if (hip_classify_update_type(ctx->input_msg) == FIRST_UPDATE_PACKET ||
132 hip_classify_update_type(ctx->input_msg) == SECOND_UPDATE_PACKET) {
133 if (hip_get_param_contents(ctx->input_msg, HIP_PARAM_CHALLENGE_REQUEST)) {
134 if (hip_add_certificate(ctx->output_msg, host_cert)) {
135 HIP_ERROR("Failed to add certificate to update message.\n");
136 return -1;
137 }
138 } else {
139 HIP_DEBUG("No middlebox found in previous update, omitting certificate.\n");
140 }
141 }
142
143 return 0;
144}
145
146/**
147 * Initialize certificate functionality in the hipd.
148 * Registers handlers to add the trust point certificate in R2 and U2 messages.
149 *
150 * @return 0 on success, negative on error
151 */
152int hip_cert_init(void)
153{
154 if (hip_register_handle_function(HIP_I2, HIP_STATE_NONE,
155 &hip_add_certificate_r2, 40500)) {
156 HIP_ERROR("Error on registering certificate handle function.\n");
157 return -1;
158 }
159 if (hip_register_handle_function(HIP_I2, HIP_STATE_UNASSOCIATED,
160 &hip_add_certificate_r2, 40500)) {
161 HIP_ERROR("Error on registering certificate handle function.\n");
162 return -1;
163 }
164 if (hip_register_handle_function(HIP_I2, HIP_STATE_I1_SENT,
165 &hip_add_certificate_r2, 40500)) {
166 HIP_ERROR("Error on registering certificate handle function.\n");
167 return -1;
168 }
169 if (hip_register_handle_function(HIP_I2, HIP_STATE_I2_SENT,
170 &hip_add_certificate_r2, 40500)) {
171 HIP_ERROR("Error on registering certificate handle function.\n");
172 return -1;
173 }
174 if (hip_register_handle_function(HIP_I2, HIP_STATE_R2_SENT,
175 &hip_add_certificate_r2, 40500)) {
176 HIP_ERROR("Error on registering certificate handle function.\n");
177 return -1;
178 }
179 if (hip_register_handle_function(HIP_I2, HIP_STATE_ESTABLISHED,
180 &hip_add_certificate_r2, 40500)) {
181 HIP_ERROR("Error on registering certificate handle function.\n");
182 return -1;
183 }
184 if (hip_register_handle_function(HIP_UPDATE, HIP_STATE_ESTABLISHED,
185 &hip_add_certificate_update, 20752)) {
186 HIP_ERROR("Error on registering certificate handle function.\n");
187 return -1;
188 }
189 if (hip_register_handle_function(HIP_UPDATE, HIP_STATE_R2_SENT,
190 &hip_add_certificate_update, 20752)) {
191 HIP_ERROR("Error on registering certificate handle function.\n");
192 return -1;
193 }
194
195 if (!(host_cert = cert_load_x509_certificate(HIPL_SYSCONFDIR "/host-cert.der",
196 ENCODING_FORMAT_DER))) {
197 HIP_DEBUG("Could not load certificate.\n");
198 }
199
200 HIP_DEBUG("certificates initialized\n");
201
202 return 0;
83}203}
84204
=== renamed file 'hipd/pisa.h' => 'modules/cert/hipd/cert.h'
--- hipd/pisa.h 2011-11-25 17:56:24 +0000
+++ modules/cert/hipd/cert.h 2012-03-09 12:45:28 +0000
@@ -1,5 +1,5 @@
1/*1/*
2 * Copyright (c) 2010 Aalto University and RWTH Aachen University.2 * Copyright (c) 2010-2011 Aalto University and RWTH Aachen University.
3 *3 *
4 * Permission is hereby granted, free of charge, to any person4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation5 * obtaining a copy of this software and associated documentation
@@ -23,22 +23,9 @@
23 * OTHER DEALINGS IN THE SOFTWARE.23 * OTHER DEALINGS IN THE SOFTWARE.
24 */24 */
2525
26/**26#ifndef HIPL_MODULES_CERT_HIPD_CERT_H
27 * @file27#define HIPL_MODULES_CERT_HIPD_CERT_H
28 * This file contains function declarations specific to PISA. They deal with the28
29 * certificate loading.29int hip_cert_init(void);
30 *30
31 * @brief Functions declarations for certificate loading31#endif /* HIPL_MODULES_CERT_HIPD_CERT_H */
32 */
33
34#ifndef HIPL_HIPD_PISA_H
35#define HIPL_HIPD_PISA_H
36
37/**
38 * Get the certificate text that will be appended to R2 and U2 packets
39 *
40 * @return pointer to the certificate text
41 */
42char *hip_pisa_get_certificate(void);
43
44#endif /* HIPL_HIPD_PISA_H */
4532
=== added file 'modules/cert/module_info.xml'
--- modules/cert/module_info.xml 1970-01-01 00:00:00 +0000
+++ modules/cert/module_info.xml 2012-03-09 12:45:28 +0000
@@ -0,0 +1,23 @@
1<?xml version="1.0" encoding="UTF-8"?>
2
3<!-- Mandatory: name, version -->
4<module
5 name="cert"
6 version="0.0.1"
7 description="certificate exchange for the HIP daemon."
8 developer=""
9 bugaddress="hipl-users@freelists.org"
10 webpage="http://infrahip.hiit.fi/">
11
12 <requires>
13 <module name="update" minversion="0.0.1" />
14 <module name="midauth" minversion="0.0.1" />
15 </requires>
16
17 <!-- Mandatory: name, header_file, init_function -->
18 <application
19 name="hipd"
20 header_file="modules/cert/hipd/cert.h"
21 init_function="hip_cert_init" />
22</module>
23
024
=== modified file 'modules/update/hipd/update.c' (properties changed: -x to +x)
=== modified file 'test/check_lib_core.c'
--- test/check_lib_core.c 2012-03-01 14:06:24 +0000
+++ test/check_lib_core.c 2012-03-09 12:45:28 +0000
@@ -37,6 +37,7 @@
37{37{
38 int number_failed;38 int number_failed;
39 SRunner *sr = srunner_create(lib_core_hit());39 SRunner *sr = srunner_create(lib_core_hit());
40 srunner_add_suite(sr, lib_core_cert());
40 srunner_add_suite(sr, lib_core_hostid());41 srunner_add_suite(sr, lib_core_hostid());
41 srunner_add_suite(sr, lib_core_solve());42 srunner_add_suite(sr, lib_core_solve());
42 srunner_add_suite(sr, lib_core_straddr());43 srunner_add_suite(sr, lib_core_straddr());
4344
=== added file 'test/lib/core/cert.c'
--- test/lib/core/cert.c 1970-01-01 00:00:00 +0000
+++ test/lib/core/cert.c 2012-03-09 12:45:28 +0000
@@ -0,0 +1,189 @@
1/*
2 * Copyright (c) 2011 Aalto University and RWTH Aachen University.
3 *
4 * Permission is hereby granted, free of charge, to any person
5 * obtaining a copy of this software and associated documentation
6 * files (the "Software"), to deal in the Software without
7 * restriction, including without limitation the rights to use,
8 * copy, modify, merge, publish, distribute, sublicense, and/or sell
9 * copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following
11 * conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
18 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
22 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 * OTHER DEALINGS IN THE SOFTWARE.
24 */
25
26#include <check.h>
27#include <stdlib.h>
28#include <string.h>
29#include <stdio.h>
30
31#include "lib/core/cert.h"
32#include "lib/core/crypto.h"
33#include "lib/core/ife.h"
34#include "lib/core/protodefs.h"
35#include "config.h"
36#include "test_suites.h"
37
38#define TEST_CERT HIPL_SOURCEDIR "/test/lib/core/test_cert.pem"
39#define TEST_KEY HIPL_SOURCEDIR "/test/lib/core/test_key.pem"
40
41START_TEST(test_cert_load_x509_certificate)
42{
43 X509 *cert = NULL;
44
45 HIP_DEBUG("Test loading of X509 certificates.\n");
46
47 fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
48 ENCODING_FORMAT_PEM)) != NULL,
49 NULL);
50 fail_unless((cert = cert_load_x509_certificate("non_existing_cert.pem",
51 ENCODING_FORMAT_PEM)) == NULL,
52 NULL);
53 fail_unless((cert = cert_load_x509_certificate(NULL,
54 ENCODING_FORMAT_PEM)) == NULL,
55 NULL);
56
57 X509_free(cert);
58 HIP_DEBUG("Successfully passed tests for loading X509 certificates.\n");
59}
60END_TEST
61
62START_TEST(test_cert_DER_encoding)
63{
64 int len = 0;
65 X509 *cert = NULL;
66 X509 *cert_decoded = NULL;
67 unsigned char *buf = NULL;
68
69 HIP_DEBUG("Test DER en/decoding of X509 certificates.\n");
70
71 fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
72 ENCODING_FORMAT_PEM)) != NULL,
73 NULL);
74 fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
75 fail_unless((cert_decoded = cert_DER_to_X509(buf, len)) != NULL, NULL);
76 fail_unless(X509_cmp(cert, cert_decoded) == 0, NULL);
77
78 fail_unless((len = cert_X509_to_DER(NULL, &buf)) < 0, NULL);
79 fail_unless((len = cert_X509_to_DER(cert, NULL)) < 0, NULL);
80 fail_unless((len = cert_X509_to_DER(NULL, NULL)) < 0, NULL);
81
82 fail_unless((cert_decoded = cert_DER_to_X509(NULL, len)) == NULL, NULL);
83 fail_unless((cert_decoded = cert_DER_to_X509(buf, len - 1)) == NULL, NULL);
84 fail_unless((cert_decoded = cert_DER_to_X509(buf, len + 1)) == NULL, NULL);
85 fail_unless((cert_decoded = cert_DER_to_X509(buf, 0)) == NULL, NULL);
86
87 X509_free(cert);
88 X509_free(cert_decoded);
89
90 HIP_DEBUG("Successfully passed tests for DER en/decoding of X509 certificates.\n");
91}
92
93END_TEST
94
95START_TEST(test_cert_match_public_key)
96{
97 int err = 0;
98 RSA *rsa = NULL;
99 X509 *cert = NULL;
100 EVP_PKEY *pkey = NULL;
101
102 HIP_DEBUG("Test matching of public keys.\n");
103
104 fail_unless((err = load_rsa_private_key(TEST_KEY, &rsa)) == 0, NULL);
105 fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
106 ENCODING_FORMAT_PEM)) != NULL,
107 NULL);
108 pkey = EVP_PKEY_new();
109 EVP_PKEY_assign_RSA(pkey, rsa);
110 fail_unless((err = cert_match_public_key(cert, pkey)) == 1, NULL);
111
112 fail_unless((err = cert_match_public_key(NULL, pkey)) == 0, NULL);
113 fail_unless((err = cert_match_public_key(cert, NULL)) == 0, NULL);
114 fail_unless((err = cert_match_public_key(NULL, NULL)) == 0, NULL);
115
116 EVP_PKEY_free(pkey);
117 X509_free(cert);
118
119 HIP_DEBUG("Successfully passed test for matching of public keys.\n");
120}
121
122END_TEST
123
124START_TEST(test_cert_verify_chain)
125{
126 int err = 0;
127 X509 *cert = NULL;
128 STACK_OF(X509) *chain = NULL;
129
130 HIP_DEBUG("Test verification of certificate chains.\n");
131
132 fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
133 ENCODING_FORMAT_PEM)) != NULL,
134 NULL);
135 fail_unless((chain = sk_X509_new_null()) != NULL, NULL);
136 sk_X509_push(chain, cert);
137 fail_unless((err = cert_verify_chain(cert, NULL, chain, NULL)) == 0, NULL);
138
139 fail_unless((err = cert_verify_chain(NULL, NULL, chain, NULL)) != 0, NULL);
140 fail_unless((err = cert_verify_chain(cert, NULL, NULL, NULL)) != 0, NULL);
141
142 HIP_DEBUG("Successfully passed test for verification of certificate chains.\n");
143}
144
145END_TEST
146
147START_TEST(test_cert_get_X509_from_msg)
148{
149 int len = 0;
150 X509 *cert = NULL, *cert2 = NULL;
151 struct hip_common *msg = NULL;
152 unsigned char *buf = NULL;
153
154 HIP_DEBUG("Test certificate extraction functionality.\n");
155
156 fail_unless((cert = cert_load_x509_certificate(TEST_CERT,
157 ENCODING_FORMAT_PEM)) != NULL,
158 NULL);
159 msg = hip_msg_alloc();
160 hip_build_network_hdr(msg, HIP_UPDATE, 0, &in6addr_any, &in6addr_any);
161 fail_unless((len = cert_X509_to_DER(cert, &buf)) > 0, NULL);
162 fail_unless(hip_build_param_cert(msg, 0, 1, 1, HIP_CERT_X509V3, buf, len) == 0, NULL);
163 fail_unless((cert2 = cert_get_X509_from_msg(msg)) != NULL, NULL);
164 fail_unless(X509_cmp(cert, cert2) == 0, NULL);
165
166 X509_free(cert);
167 X509_free(cert2);
168
169 HIP_DEBUG("Successfully passed test for certificate extraction functionality.\n");
170}
171
172END_TEST
173
174
175Suite *lib_core_cert(void)
176{
177 Suite *s = suite_create("lib/core/cert");
178
179 TCase *tc_core = tcase_create("Core");
180 tcase_add_test(tc_core, test_cert_load_x509_certificate);
181 tcase_add_test(tc_core, test_cert_DER_encoding);
182 tcase_add_test(tc_core, test_cert_match_public_key);
183 tcase_add_test(tc_core, test_cert_verify_chain);
184 tcase_add_test(tc_core, test_cert_get_X509_from_msg);
185
186 suite_add_tcase(s, tc_core);
187
188 return s;
189}
0190
=== added file 'test/lib/core/test_cert.pem'
--- test/lib/core/test_cert.pem 1970-01-01 00:00:00 +0000
+++ test/lib/core/test_cert.pem 2012-03-09 12:45:28 +0000
@@ -0,0 +1,15 @@
1-----BEGIN CERTIFICATE-----
2MIICWTCCAcKgAwIBAgIJAPRDK58Gc992MA0GCSqGSIb3DQEBBQUAMCgxCzAJBgNV
3BAYTAkRFMRkwFwYDVQQDExBUZXN0IENlcnRpZmljYXRlMB4XDTExMTExNTA4NDYx
4MloXDTE0MDgxMTA4NDYxMlowKDELMAkGA1UEBhMCREUxGTAXBgNVBAMTEFRlc3Qg
5Q2VydGlmaWNhdGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAMn5azBSwPlu
6DIzEhd6fGdo1+ze9uS+i+AbifvjHKYaDwDZktANnUmTuLNAXoeVtFi5GH/5aczUx
7rFaW+XT33oO1OjotZOHvoQd5cVAvXTtzuJj9PnBtA0lkrQ36f765p65Id0+Xme3o
8sXfqLsJy12C23RjisPgAo0hsLUFXt+FZAgMBAAGjgYowgYcwHQYDVR0OBBYEFGrj
9JefuwL7xAFj9NZoDVksjz1JBMFgGA1UdIwRRME+AFGrjJefuwL7xAFj9NZoDVksj
10z1JBoSykKjAoMQswCQYDVQQGEwJERTEZMBcGA1UEAxMQVGVzdCBDZXJ0aWZpY2F0
11ZYIJAPRDK58Gc992MAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAKX5Q
120di8aNk1Js5Sk6QstSWwoVT9DUNZ8wKKRZVHy4kSL7dGMNGRPyNydzJmKeacbZJ0
13wM64rMMC1E8Wnyo+7eS1k9NKgaR5S1K6SVTfgP0HYIeJquD5Im/KW3aMz/q5CWdV
14IZtpTC2/1YsK+dVlvvcYRxnSTpIEd/pmu574lis=
15-----END CERTIFICATE-----
016
=== added file 'test/lib/core/test_key.pem'
--- test/lib/core/test_key.pem 1970-01-01 00:00:00 +0000
+++ test/lib/core/test_key.pem 2012-03-09 12:45:28 +0000
@@ -0,0 +1,15 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIICXAIBAAKBgQDJ+WswUsD5bgyMxIXenxnaNfs3vbkvovgG4n74xymGg8A2ZLQD
3Z1Jk7izQF6HlbRYuRh/+WnM1MaxWlvl0996DtTo6LWTh76EHeXFQL107c7iY/T5w
4bQNJZK0N+n++uaeuSHdPl5nt6LF36i7Cctdgtt0Y4rD4AKNIbC1BV7fhWQIDAQAB
5AoGAT1OS8evOtyit7SvSmFlMwhOpk38EmN0dJTcYP4WZnadpevOacCvIhLO3DhP6
6Fi3+JDaOokvMK/xSf7/UQkiIL+dwY5FtWtG6K+T1WI4+DR7ULShr82jh4KemhYv3
7Xz6PvEBIUrf64VfsNsAzoWvbwum/Ev1XzFn5YS4/EW3ApnECQQD2YW6tTjzyq3y7
8sgil9/VtUrXpPi5Ekm8l/bFW2Ijwin03g6J+YvkDNIq5Wwyka7lBOLwpdSpzT2qB
970Ne1nlfAkEA0dwlgou4xOVVmbtTb40FxIFgd2gDQO8bUFEa+TdPWLLxz9yxHQ7D
10YROYh5Gdi0u4lz0KNex/6zyaP7E+utbIRwJAexNc2FH2/DpSCuj6jP36qevhV2xq
11bHLB9zZtujZc4dwshOjK6VvDjKhYjBNBk3kEh+IxjHwtAoEvcUz2WI/G/QJAcMr5
12/ihKrsj0MSRVu+b36p3+0y68UPIypABzlu77XpkPDsF3ED8XE94MZREGtA+GrwLH
13siPivPRdk04YgSNfkQJBAMhHvxL5xsb31bu8h7kxoYHj/XuqJxyToTcqksr7M1RO
14z33Bid+znwnB7n8CLFpV3iqF14xbRKiPlc//wVNWtZ8=
15-----END RSA PRIVATE KEY-----
016
=== modified file 'test/lib/core/test_suites.h'
--- test/lib/core/test_suites.h 2012-03-01 14:06:24 +0000
+++ test/lib/core/test_suites.h 2012-03-09 12:45:28 +0000
@@ -28,6 +28,7 @@
2828
29#include <check.h>29#include <check.h>
3030
31Suite *lib_core_cert(void);
31Suite *lib_core_crypto(void);32Suite *lib_core_crypto(void);
32Suite *lib_core_hit(void);33Suite *lib_core_hit(void);
33Suite *lib_core_hostid(void);34Suite *lib_core_hostid(void);
3435
=== modified file 'tools/hipl_autobuild.sh'
--- tools/hipl_autobuild.sh 2012-02-28 16:54:46 +0000
+++ tools/hipl_autobuild.sh 2012-03-09 12:45:28 +0000
@@ -169,7 +169,7 @@
169run_program "make $MAKEOPTS check"169run_program "make $MAKEOPTS check"
170170
171# minimal configuration171# minimal configuration
172compile --enable-firewall --disable-rvs --disable-profiling --disable-debug --disable-performance --with-nomodules=heartbeat,update,heartbeat_update,midauth172compile --enable-firewall --disable-rvs --disable-profiling --disable-debug --disable-performance --with-nomodules=heartbeat,update,heartbeat_update,midauth,cert
173173
174# Max compile coverage configuration174# Max compile coverage configuration
175FEATURES_ALL="--enable-firewall --enable-rvs --enable-profiling --disable-debug --enable-performance"175FEATURES_ALL="--enable-firewall --enable-rvs --enable-profiling --disable-debug --enable-performance"
@@ -185,9 +185,6 @@
185# FIXME: Disabled until the tree compiles with this optimization level.185# FIXME: Disabled until the tree compiles with this optimization level.
186#compile $FEATURES_ALL CFLAGS="-O3"186#compile $FEATURES_ALL CFLAGS="-O3"
187187
188# Without modules
189compile --with-nomodules=heartbeat,update,heartbeat_update,midauth
190
191# test binary distribution packages188# test binary distribution packages
192# This is run as the last test because it can have sideeffects on the189# This is run as the last test because it can have sideeffects on the
193# other standard configurations.190# other standard configurations.

Subscribers

People subscribed via source and target branches

to all changes: