Adding SSL certs to Bro 2.0

Hi! I've been testing the 2.0 beta (kudos, btw). My alarm files is
getting tons of SSL::Invalid_Server_Cert from our own local certs,
doegrid certs, cern.ch, fnal.gov, presumably because the root CA cert
for those is not included with either Bro or the OS.

I see share/bro/base/protocols/ssl/mozilla-ca-list has a bundle of root
CA certs. Is there a way to add our own to that or to a separate file?
  How is that file generated? Thanks.

Mat

share/bro/site/local.bro

redef the list to append your local entries.

Sridhar

Hi! I've been testing the 2.0 beta (kudos, btw).

Great, thanks!

I see share/bro/base/protocols/ssl/mozilla-ca-list has a bundle of root
CA certs. Is there a way to add our own to that or to a separate file?
How is that file generated? Thanks.

We have a exercise from the workshop that specifically addresses this situation. We will be posting the workshop material really soon too.

Ultimately, you need to take a DER formatted version of your root public key and convert it to Bro's hex string representation and add it to the SSL::root_certs table. Like this....

redef SSL::root_certs += {
  ["your root certificates subject"] = "\x30\x82\x03\x75\x30\x82<snip a lot more of this>";
};

You can add that to the bottom of your local.bro file as Sridhar recommended.

  .Seth

The semicolon at the end of the second line errors. Removing it causes it to work.

If anyone's interested, I have a sloppy python script that will take a "standard" .pem cert and output a valid "redef SSL::root_certs += {..." stanza like the one Seth wrote. I tested it with the cacert root sig and it's happy with my certs now. :slight_smile:

-Lou

I would definitely be interested.

Mat

I heard back from some of the guys at FNAL, and they pointed out the
FNAL CA cert is part of the IGTF distro:

  http://www.igtf.net

and 3 tarball of certs at:

   https://dist.eugridpma.info/distribution/igtf/current/accredited/

That covers most of the major scientific/research CA's I know of.
Adding those to Bro would complement the list of commercial CA's
extracted from Mozilla.

Mat

Ah, cool. I think this might make a good contribution to the upcoming contributed scripts repository. We are still trying to iron out the details about how it will work, but it is coming.

The Mozilla root CA list might even get moved to the contributed scripts repository eventually so that we can keep it updated more easily between releases.

  .Seth

2011-11-16 13:16:40 -0500, Seth Hall:
[...]

> I see share/bro/base/protocols/ssl/mozilla-ca-list has a bundle of root
> CA certs. Is there a way to add our own to that or to a separate file?
> How is that file generated? Thanks.

We have a exercise from the workshop that specifically addresses this situation. We will be posting the workshop material really soon too.

Ultimately, you need to take a DER formatted version of your root public key and convert it to Bro's hex string representation and add it to the SSL::root_certs table. Like this....

redef SSL::root_certs += {
  ["your root certificates subject"] = "\x30\x82\x03\x75\x30\x82<snip a lot more of this>";
};

[...]

In case it may be of some help to anyone, here is a script to
convert a PEM CA cert bundle such as
/etc/ssl/certs/ca-certificates.crt as found on debian based
system to bro's format:

<BEGIN>
#! /usr/bin/perl
use Encode;
use Crypt::OpenSSL::X509;

while (<>) {
  if (/BEGIN /) {
    $p="";
    $inside=1;
  }
  p \.= _ if $inside;
  if (/END /) {
    $c = Crypt::OpenSSL::X509->new_from_string(p\); &nbsp;&nbsp;&nbsp;&nbsp;@s = map \{ _->as_string } reverse @{$c->subject_name->entries};
    s/[\\,]/\\$&/g for @s;
    $s = join ",", @s;
    $s = encode("UTF-8", $s);
    s =\~ s/\[\\200\-\\377\]/sprintf\(&quot;\\\\%X&quot;,ord&)/ge;
    x = join &quot;&quot;, map \{ &quot;\\\\x&quot; \. uc_ } unpack("(H2)*", $c->as_string(Crypt::OpenSSL::X509::FORMAT_ASN1));
    print "\t[\"$s\"] = \"$x\",\n"; $inside = 0;
  }
}
<END>

(this gives the same output as found in the mozilla-ca.bro file)

Then, I have a /etc/ca-certificates/update.d/bro-cacerts to
update Bro's root_certs everytime the system CA certs are
updated:

<BEGIN>
#! /bin/sh -
BRO_CERTSTORE=/usr/local/share/bro/site/certs.bro

if [ -f /etc/default/cacerts ]; then
    . /etc/default/cacerts
fi

echo
if [ "$cacerts_updates" != yes ] || [ "$CACERT_UPDATES" = disabled ]; then
    echo "updates of cacerts keystore disabled."
    exit 0
fi

printf '%s\n' "Updating Bro IDS CA Cert store $BRO_CERTSTORE"

set -C
{
  echo "redef SSL::root_certs += {" &&
    /usr/local/bin/crt-to-bro < /etc/ssl/certs/ca-certificates.crt &&
    echo "};"
} > "$BRO_CERTSTORE.new" || exit
mv -f "$BRO_CERTSTORE.new" "$BRO_CERTSTORE" || exit

echo "Restarting bro"
broctl check &&
  broctl install &&
  broctl restart
<END>

This way, Bro uses the same rootca as the system's to verify
certificates.

HTH
Stephane

Cool, thanks. We have a script in bro-aux that generates the CA list Bro script directly from the Mozilla repository too. If you have a copy of our source tree, the script is here:
  aux/bro-aux/devel-tools/gen-mozilla-ca-list.rb

  .Seth

Quick question. I am getting a timeout when trying to print the
variable containing the root_certs. I am just wondering if this is due
to having too many trusted certs loaded or if this is just a
limitation of the broctl print function. My primary concern is whether
bro was actually able to load all the root_certs on startup. I have
over 500 certs redef'd in site/mytrustedcerts.bro. Is this too many
for bro to handle?

broctl print SSL::root_certs
manager <error: time-out>
proxy-1 <error: time-out>
worker-1 <error: time-out>
worker-2 <error: time-out>
worker-3 <error: time-out>
worker-4 <error: time-out>
worker-5 <error: time-out>
worker-6 <error: time-out>
worker-7 <error: time-out>
worker-8 <error: time-out>

Thanks!

-will

Pretty certainly the latter, the table itself shouldn't have a problem
with many entries. Bro's current git version has a new option to
increase the BroControl timeout for print, but here's another thing
you can do to see the output:

Add this to your local.bro:

    event bro_init()
    {
        print SSL::root_certs;
    }

Get a small trace and run it through broctl's "process" command:

    broctl process path/to/trace

This will print all the certs to stdout (and then process the trace).

(Trace content doesn't matter; one of Bro's test traces will do, like
bro/testing/btest/Traces/web.trace).

Robin

Quick question. I am getting a timeout when trying to print the
variable containing the root_certs. I am just wondering if this is due
to having too many trusted certs loaded or if this is just a
limitation of the broctl print function.

Pretty certainly the latter, the table itself shouldn't have a problem
with many entries. Bro's current git version has a new option to
increase the BroControl timeout for print, but here's another thing
you can do to see the output:

Excellent! Thanks Robin!

Add this to your local.bro:

event bro_init()
{
print SSL::root_certs;
}

Get a small trace and run it through broctl's "process" command:

broctl process path/to/trace

This will print all the certs to stdout (and then process the trace).

(Trace content doesn't matter; one of Bro's test traces will do, like
bro/testing/btest/Traces/web.trace).

Much appreciated!