output validity of raw public key if available
[strongswan.git] / src / libcharon / plugins / stroke / stroke_list.c
index bc9fc02..514a91e 100644 (file)
 
 #include "stroke_list.h"
 
 
 #include "stroke_list.h"
 
+#include <inttypes.h>
 #include <time.h>
 
 #ifdef HAVE_MALLINFO
 #include <malloc.h>
 #endif /* HAVE_MALLINFO */
 
 #include <time.h>
 
 #ifdef HAVE_MALLINFO
 #include <malloc.h>
 #endif /* HAVE_MALLINFO */
 
+#include <hydra.h>
 #include <daemon.h>
 #include <utils/linked_list.h>
 #include <daemon.h>
 #include <utils/linked_list.h>
+#include <plugins/plugin.h>
 #include <credentials/certificates/x509.h>
 #include <credentials/certificates/ac.h>
 #include <credentials/certificates/crl.h>
 #include <credentials/certificates/x509.h>
 #include <credentials/certificates/ac.h>
 #include <credentials/certificates/crl.h>
@@ -115,7 +118,7 @@ static void log_ike_sa(FILE *out, ike_sa_t *ike_sa, bool all)
 
                ike_proposal = ike_sa->get_proposal(ike_sa);
 
 
                ike_proposal = ike_sa->get_proposal(ike_sa);
 
-               fprintf(out, "%12s[%d]: IKE SPIs: %.16llx_i%s %.16llx_r%s",
+               fprintf(out, "%12s[%d]: IKE SPIs: %.16"PRIx64"_i%s %.16"PRIx64"_r%s",
                                ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
                                id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
                                id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
                                ike_sa->get_name(ike_sa), ike_sa->get_unique_id(ike_sa),
                                id->get_initiator_spi(id), id->is_initiator(id) ? "*" : "",
                                id->get_responder_spi(id), id->is_initiator(id) ? "" : "*");
@@ -220,11 +223,14 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
                        {
                                u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
                                u_int16_t encr_size = 0, int_size = 0;
                        {
                                u_int16_t encr_alg = ENCR_UNDEFINED, int_alg = AUTH_UNDEFINED;
                                u_int16_t encr_size = 0, int_size = 0;
+                               u_int16_t esn = NO_EXT_SEQ_NUMBERS;
 
                                proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
                                                                                &encr_alg, &encr_size);
                                proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
                                                                                &int_alg, &int_size);
 
                                proposal->get_algorithm(proposal, ENCRYPTION_ALGORITHM,
                                                                                &encr_alg, &encr_size);
                                proposal->get_algorithm(proposal, INTEGRITY_ALGORITHM,
                                                                                &int_alg, &int_size);
+                               proposal->get_algorithm(proposal, EXTENDED_SEQUENCE_NUMBERS,
+                                                                               &esn, NULL);
 
                                if (encr_alg != ENCR_UNDEFINED)
                                {
 
                                if (encr_alg != ENCR_UNDEFINED)
                                {
@@ -242,21 +248,25 @@ static void log_child_sa(FILE *out, child_sa_t *child_sa, bool all)
                                                fprintf(out, "_%u", int_size);
                                        }
                                }
                                                fprintf(out, "_%u", int_size);
                                        }
                                }
+                               if (esn == EXT_SEQ_NUMBERS)
+                               {
+                                       fprintf(out, "/ESN");
+                               }
                        }
 
                        now = time_monotonic(NULL);
                        child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
                        }
 
                        now = time_monotonic(NULL);
                        child_sa->get_usestats(child_sa, TRUE, &use_in, &bytes_in);
-                       fprintf(out, ", %llu bytes_i", bytes_in);
+                       fprintf(out, ", %" PRIu64 " bytes_i", bytes_in);
                        if (use_in)
                        {
                        if (use_in)
                        {
-                               fprintf(out, " (%ds ago)", now - use_in);
+                               fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_in));
                        }
 
                        child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out);
                        }
 
                        child_sa->get_usestats(child_sa, FALSE, &use_out, &bytes_out);
-                       fprintf(out, ", %llu bytes_o", bytes_out);
+                       fprintf(out, ", %" PRIu64 " bytes_o", bytes_out);
                        if (use_out)
                        {
                        if (use_out)
                        {
-                               fprintf(out, " (%ds ago)", now - use_out);
+                               fprintf(out, " (%" PRIu64 "s ago)", (u_int64_t)(now - use_out));
                        }
                        fprintf(out, ", rekeying ");
 
                        }
                        fprintf(out, ", rekeying ");
 
@@ -323,7 +333,7 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
                        {
                                if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
                                {
                        {
                                if ((uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR))
                                {
-                                       fprintf(out, "EAP_%d-%d authentication",
+                                       fprintf(out, "EAP_%" PRIuPTR "-%" PRIuPTR " authentication",
                                                (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
                                                (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
                                }
                                                (uintptr_t)auth->get(auth, AUTH_RULE_EAP_TYPE),
                                                (uintptr_t)auth->get(auth, AUTH_RULE_EAP_VENDOR));
                                }
@@ -387,27 +397,28 @@ static void log_auth_cfgs(FILE *out, peer_cfg_t *peer_cfg, bool local)
        enumerator->destroy(enumerator);
 }
 
        enumerator->destroy(enumerator);
 }
 
-/**
- * Implementation of stroke_list_t.status.
- */
-static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bool all)
+METHOD(stroke_list_t, status, void,
+       private_stroke_list_t *this, stroke_msg_t *msg, FILE *out,
+       bool all, bool wait)
 {
        enumerator_t *enumerator, *children;
        ike_cfg_t *ike_cfg;
        child_cfg_t *child_cfg;
        child_sa_t *child_sa;
        ike_sa_t *ike_sa;
 {
        enumerator_t *enumerator, *children;
        ike_cfg_t *ike_cfg;
        child_cfg_t *child_cfg;
        child_sa_t *child_sa;
        ike_sa_t *ike_sa;
+       linked_list_t *my_ts, *other_ts;
        bool first, found = FALSE;
        char *name = msg->status.name;
        bool first, found = FALSE;
        char *name = msg->status.name;
+       u_int half_open;
 
        if (all)
        {
                peer_cfg_t *peer_cfg;
 
        if (all)
        {
                peer_cfg_t *peer_cfg;
-               char *plugin, *pool;
+               char *pool;
                host_t *host;
                u_int32_t dpd;
                time_t since, now;
                host_t *host;
                u_int32_t dpd;
                time_t since, now;
-               u_int size, online, offline;
+               u_int size, online, offline, i;
                now = time_monotonic(NULL);
                since = time(NULL) - (now - this->uptime);
 
                now = time_monotonic(NULL);
                since = time(NULL) - (now - this->uptime);
 
@@ -421,21 +432,24 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                                    mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
                }
 #endif /* HAVE_MALLINFO */
                                    mi.arena, mi.hblkhd, mi.uordblks, mi.fordblks);
                }
 #endif /* HAVE_MALLINFO */
-               fprintf(out, "  worker threads: %d idle of %d,",
-                               charon->processor->get_idle_threads(charon->processor),
-                               charon->processor->get_total_threads(charon->processor));
-               fprintf(out, " job queue load: %d,",
-                               charon->processor->get_job_load(charon->processor));
-               fprintf(out, " scheduled events: %d\n",
-                               charon->scheduler->get_job_load(charon->scheduler));
-               fprintf(out, "  loaded plugins: ");
-               enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
-               while (enumerator->enumerate(enumerator, &plugin))
+               fprintf(out, "  worker threads: %d of %d idle, ",
+                               lib->processor->get_idle_threads(lib->processor),
+                               lib->processor->get_total_threads(lib->processor));
+               for (i = 0; i < JOB_PRIO_MAX; i++)
                {
                {
-                       fprintf(out, "%s ", plugin);
+                       fprintf(out, "%s%d", i == 0 ? "" : "/",
+                                       lib->processor->get_working_threads(lib->processor, i));
                }
                }
-               enumerator->destroy(enumerator);
-               fprintf(out, "\n");
+               fprintf(out, " working, job queue: ");
+               for (i = 0; i < JOB_PRIO_MAX; i++)
+               {
+                       fprintf(out, "%s%d", i == 0 ? "" : "/",
+                                       lib->processor->get_job_load(lib->processor, i));
+               }
+               fprintf(out, ", scheduled: %d\n",
+                               lib->scheduler->get_job_load(lib->scheduler));
+               fprintf(out, "  loaded plugins: %s\n",
+                               lib->plugins->loaded_plugins(lib->plugins));
 
                first = TRUE;
                enumerator = this->attribute->create_pool_enumerator(this->attribute);
 
                first = TRUE;
                enumerator = this->attribute->create_pool_enumerator(this->attribute);
@@ -454,8 +468,8 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                }
                enumerator->destroy(enumerator);
 
                }
                enumerator->destroy(enumerator);
 
-               enumerator = charon->kernel_interface->create_address_enumerator(
-                                                               charon->kernel_interface, FALSE, FALSE);
+               enumerator = hydra->kernel_interface->create_address_enumerator(
+                                                                       hydra->kernel_interface, FALSE, FALSE);
                fprintf(out, "Listening IP addresses:\n");
                while (enumerator->enumerate(enumerator, (void**)&host))
                {
                fprintf(out, "Listening IP addresses:\n");
                while (enumerator->enumerate(enumerator, (void**)&host))
                {
@@ -491,12 +505,11 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                        children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                        while (children->enumerate(children, &child_cfg))
                        {
                        children = peer_cfg->create_child_cfg_enumerator(peer_cfg);
                        while (children->enumerate(children, &child_cfg))
                        {
-                               linked_list_t *my_ts, *other_ts;
-
                                my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
                                other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
                                my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
                                other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
-                               fprintf(out, "%12s:   child:  %#R=== %#R", child_cfg->get_name(child_cfg),
-                                               my_ts, other_ts);
+                               fprintf(out, "%12s:   child:  %#R=== %#R%N",
+                                               child_cfg->get_name(child_cfg), my_ts, other_ts,
+                                               ipsec_mode_names, child_cfg->get_mode(child_cfg));
                                my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
                                other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
 
                                my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
                                other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
 
@@ -512,10 +525,39 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                enumerator->destroy(enumerator);
        }
 
                enumerator->destroy(enumerator);
        }
 
+       /* Enumerate shunt policies */
+       first = TRUE;
+       enumerator = charon->shunts->create_enumerator(charon->shunts);
+       while (enumerator->enumerate(enumerator, &child_cfg))
+       {
+               if (name && !streq(name, child_cfg->get_name(child_cfg)))
+               {
+                       continue;
+               }
+               if (first)
+               {
+                       fprintf(out, "Shunted Connections:\n");
+                       first = FALSE;
+               }
+               my_ts = child_cfg->get_traffic_selectors(child_cfg, TRUE, NULL, NULL);
+               other_ts = child_cfg->get_traffic_selectors(child_cfg, FALSE, NULL, NULL);
+               fprintf(out, "%12s:  %#R=== %#R%N\n",
+                               child_cfg->get_name(child_cfg), my_ts, other_ts,
+                               ipsec_mode_names, child_cfg->get_mode(child_cfg));
+               my_ts->destroy_offset(my_ts, offsetof(traffic_selector_t, destroy));
+               other_ts->destroy_offset(other_ts, offsetof(traffic_selector_t, destroy));
+       }
+       enumerator->destroy(enumerator);
+
+       /* Enumerate traps */
        first = TRUE;
        enumerator = charon->traps->create_enumerator(charon->traps);
        while (enumerator->enumerate(enumerator, NULL, &child_sa))
        {
        first = TRUE;
        enumerator = charon->traps->create_enumerator(charon->traps);
        while (enumerator->enumerate(enumerator, NULL, &child_sa))
        {
+               if (name && !streq(name, child_sa->get_name(child_sa)))
+               {
+                       continue;
+               }
                if (first)
                {
                        fprintf(out, "Routed Connections:\n");
                if (first)
                {
                        fprintf(out, "Routed Connections:\n");
@@ -525,12 +567,17 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
        }
        enumerator->destroy(enumerator);
 
        }
        enumerator->destroy(enumerator);
 
-       fprintf(out, "Security Associations:\n");
-       enumerator = charon->controller->create_ike_sa_enumerator(charon->controller);
+       half_open = charon->ike_sa_manager->get_half_open_count(
+                                                                                               charon->ike_sa_manager, NULL);
+       fprintf(out, "Security Associations (%u up, %u connecting):\n",
+               charon->ike_sa_manager->get_count(charon->ike_sa_manager) - half_open,
+               half_open);
+       enumerator = charon->controller->create_ike_sa_enumerator(
+                                                                                                       charon->controller, wait);
        while (enumerator->enumerate(enumerator, &ike_sa))
        {
                bool ike_printed = FALSE;
        while (enumerator->enumerate(enumerator, &ike_sa))
        {
                bool ike_printed = FALSE;
-               iterator_t *children = ike_sa->create_child_sa_iterator(ike_sa);
+               enumerator_t *children = ike_sa->create_child_sa_enumerator(ike_sa);
 
                if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
                {
 
                if (name == NULL || streq(name, ike_sa->get_name(ike_sa)))
                {
@@ -539,7 +586,7 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
                        ike_printed = TRUE;
                }
 
                        ike_printed = TRUE;
                }
 
-               while (children->iterate(children, (void**)&child_sa))
+               while (children->enumerate(children, (void**)&child_sa))
                {
                        if (name == NULL || streq(name, child_sa->get_name(child_sa)))
                        {
                {
                        if (name == NULL || streq(name, child_sa->get_name(child_sa)))
                        {
@@ -576,42 +623,36 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
 static linked_list_t* create_unique_cert_list(certificate_type_t type)
 {
        linked_list_t *list = linked_list_create();
 static linked_list_t* create_unique_cert_list(certificate_type_t type)
 {
        linked_list_t *list = linked_list_create();
-       enumerator_t *enumerator = charon->credentials->create_cert_enumerator(
-                                                                       charon->credentials, type, KEY_ANY,
-                                                                       NULL, FALSE);
+       enumerator_t *enumerator = lib->credmgr->create_cert_enumerator(
+                                                                       lib->credmgr, type, KEY_ANY, NULL, FALSE);
        certificate_t *cert;
 
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
        certificate_t *cert;
 
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
-               iterator_t *iterator = list->create_iterator(list, TRUE);
+               enumerator_t *added = list->create_enumerator(list);
                identification_t *issuer = cert->get_issuer(cert);
                identification_t *issuer = cert->get_issuer(cert);
-               bool previous_same, same = FALSE, last = TRUE;
+               bool previous_same, same = FALSE, found = FALSE;
                certificate_t *list_cert;
 
                certificate_t *list_cert;
 
-               while (iterator->iterate(iterator, (void**)&list_cert))
+               while (added->enumerate(added, (void**)&list_cert))
                {
                {
-                       /* exit if we have a duplicate? */
                        if (list_cert->equals(list_cert, cert))
                        if (list_cert->equals(list_cert, cert))
-                       {
-                               last = FALSE;
+                       {       /* stop if we found a duplicate*/
+                               found = TRUE;
                                break;
                        }
                                break;
                        }
-                       /* group certificates with same issuer */
                        previous_same = same;
                        same = list_cert->has_issuer(list_cert, issuer);
                        if (previous_same && !same)
                        previous_same = same;
                        same = list_cert->has_issuer(list_cert, issuer);
                        if (previous_same && !same)
-                       {
-                               iterator->insert_before(iterator, (void *)cert->get_ref(cert));
-                               last = FALSE;
+                       {       /* group certificates with same issuer */
                                break;
                        }
                }
                                break;
                        }
                }
-               iterator->destroy(iterator);
-
-               if (last)
+               if (!found)
                {
                {
-                       list->insert_last(list, (void *)cert->get_ref(cert));
+                       list->insert_before(list, added, cert->get_ref(cert));
                }
                }
+               added->destroy(added);
        }
        enumerator->destroy(enumerator);
        return list;
        }
        enumerator->destroy(enumerator);
        return list;
@@ -627,11 +668,11 @@ static void list_public_key(public_key_t *public, FILE *out)
        identification_t *id;
        auth_cfg_t *auth;
 
        identification_t *id;
        auth_cfg_t *auth;
 
-       if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+       if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
        {
                id = identification_create_from_encoding(ID_KEY_ID, keyid);
                auth = auth_cfg_create();
        {
                id = identification_create_from_encoding(ID_KEY_ID, keyid);
                auth = auth_cfg_create();
-               private = charon->credentials->get_private(charon->credentials,
+               private = lib->credmgr->get_private(lib->credmgr,
                                                                        public->get_type(public), id, auth);
                auth->destroy(auth);
                id->destroy(id);
                                                                        public->get_type(public), id, auth);
                auth->destroy(auth);
                id->destroy(id);
@@ -639,13 +680,13 @@ static void list_public_key(public_key_t *public, FILE *out)
 
        fprintf(out, "  pubkey:    %N %d bits%s\n",
                        key_type_names, public->get_type(public),
 
        fprintf(out, "  pubkey:    %N %d bits%s\n",
                        key_type_names, public->get_type(public),
-                       public->get_keysize(public) * 8,
+                       public->get_keysize(public),
                        private ? ", has private key" : "");
                        private ? ", has private key" : "");
-       if (public->get_fingerprint(public, KEY_ID_PUBKEY_INFO_SHA1, &keyid))
+       if (public->get_fingerprint(public, KEYID_PUBKEY_INFO_SHA1, &keyid))
        {
                fprintf(out, "  keyid:     %#B\n", &keyid);
        }
        {
                fprintf(out, "  keyid:     %#B\n", &keyid);
        }
-       if (public->get_fingerprint(public, KEY_ID_PUBKEY_SHA1, &keyid))
+       if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1, &keyid))
        {
                fprintf(out, "  subjkey:   %#B\n", &keyid);
        }
        {
                fprintf(out, "  subjkey:   %#B\n", &keyid);
        }
@@ -658,12 +699,14 @@ static void list_public_key(public_key_t *public, FILE *out)
 static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
 {
        bool first = TRUE;
 static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
 {
        bool first = TRUE;
-
-       enumerator_t *enumerator = list->create_enumerator(list);
+       time_t now = time(NULL), notBefore, notAfter;
+       enumerator_t *enumerator;
        certificate_t *cert;
 
        certificate_t *cert;
 
+       enumerator = list->create_enumerator(list);
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
+               identification_t *subject = cert->get_subject(cert);
                public_key_t *public = cert->get_public_key(cert);
 
                if (public)
                public_key_t *public = cert->get_public_key(cert);
 
                if (public)
@@ -676,6 +719,41 @@ static void stroke_list_pubkeys(linked_list_t *list, bool utc, FILE *out)
                        }
                        fprintf(out, "\n");
 
                        }
                        fprintf(out, "\n");
 
+                       /* list subject if available */
+                       if (subject->get_type(subject) != ID_KEY_ID)
+                       {
+                               fprintf(out, "  subject:   %#Y\n", subject);
+                       }
+
+                       /* list validity if available*/
+                       cert->get_validity(cert, &now, &notBefore, &notAfter);
+                       if (notBefore != UNDEFINED_TIME && notAfter != UNDEFINED_TIME)
+                       {
+                               fprintf(out, "  validity:  not before %T, ", &notBefore, utc);
+                               if (now < notBefore)
+                               {
+                                       fprintf(out, "not valid yet (valid in %V)\n", &now, &notBefore);
+                               }
+                               else
+                               {
+                                       fprintf(out, "ok\n");
+                               }
+                               fprintf(out, "             not after  %T, ", &notAfter, utc);
+                               if (now > notAfter)
+                               {
+                                       fprintf(out, "expired (%V ago)\n", &now, &notAfter);
+                               }
+                               else
+                               {
+                                       fprintf(out, "ok");
+                                       if (now > notAfter - CERT_WARNING_INTERVAL * 60 * 60 * 24)
+                                       {
+                                               fprintf(out, " (expires in %V)", &now, &notAfter);
+                                       }
+                                       fprintf(out, " \n");
+                               }
+                       }
+
                        list_public_key(public, out);
                        public->destroy(public);
                }
                        list_public_key(public, out);
                        public->destroy(public);
                }
@@ -756,7 +834,7 @@ static void stroke_list_certs(linked_list_t *list, char *label,
                        enumerator_t *enumerator;
                        identification_t *altName;
                        bool first_altName = TRUE;
                        enumerator_t *enumerator;
                        identification_t *altName;
                        bool first_altName = TRUE;
-                       int pathlen;
+                       u_int pathlen;
                        chunk_t serial, authkey;
                        time_t notBefore, notAfter;
                        public_key_t *public;
                        chunk_t serial, authkey;
                        time_t notBefore, notAfter;
                        public_key_t *public;
@@ -792,7 +870,7 @@ static void stroke_list_certs(linked_list_t *list, char *label,
 
                        fprintf(out, "  subject:  \"%Y\"\n", cert->get_subject(cert));
                        fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
 
                        fprintf(out, "  subject:  \"%Y\"\n", cert->get_subject(cert));
                        fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
-                       serial = x509->get_serial(x509);
+                       serial = chunk_skip_zero(x509->get_serial(x509));
                        fprintf(out, "  serial:    %#B\n", &serial);
 
                        /* list validity */
                        fprintf(out, "  serial:    %#B\n", &serial);
 
                        /* list validity */
@@ -836,10 +914,10 @@ static void stroke_list_certs(linked_list_t *list, char *label,
                        }
 
                        /* list optional pathLenConstraint */
                        }
 
                        /* list optional pathLenConstraint */
-                       pathlen = x509->get_pathLenConstraint(x509);
-                       if (pathlen != X509_NO_PATH_LEN_CONSTRAINT)
+                       pathlen = x509->get_constraint(x509, X509_PATH_LEN);
+                       if (pathlen != X509_NO_CONSTRAINT)
                        {
                        {
-                               fprintf(out, "  pathlen:   %d\n", pathlen);
+                               fprintf(out, "  pathlen:   %u\n", pathlen);
                        }
 
                        /* list optional ipAddrBlocks */
                        }
 
                        /* list optional ipAddrBlocks */
@@ -905,7 +983,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
                {
                        fprintf(out, "  hissuer:  \"%Y\"\n", id);
                }
                {
                        fprintf(out, "  hissuer:  \"%Y\"\n", id);
                }
-               chunk = ac->get_holderSerial(ac);
+               chunk = chunk_skip_zero(ac->get_holderSerial(ac));
                if (chunk.ptr)
                {
                        fprintf(out, "  hserial:   %#B\n", &chunk);
                if (chunk.ptr)
                {
                        fprintf(out, "  hserial:   %#B\n", &chunk);
@@ -917,7 +995,7 @@ static void stroke_list_acerts(linked_list_t *list, bool utc, FILE *out)
                        groups->destroy(groups);
                }
                fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
                        groups->destroy(groups);
                }
                fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
-               chunk  = ac->get_serial(ac);
+               chunk  = chunk_skip_zero(ac->get_serial(ac));
                fprintf(out, "  serial:    %#B\n", &chunk);
 
                /* list validity */
                fprintf(out, "  serial:    %#B\n", &chunk);
 
                /* list validity */
@@ -974,11 +1052,16 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
                fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
 
                /* list optional crlNumber */
                fprintf(out, "  issuer:   \"%Y\"\n", cert->get_issuer(cert));
 
                /* list optional crlNumber */
-               chunk = crl->get_serial(crl);
+               chunk = chunk_skip_zero(crl->get_serial(crl));
                if (chunk.ptr)
                {
                        fprintf(out, "  serial:    %#B\n", &chunk);
                }
                if (chunk.ptr)
                {
                        fprintf(out, "  serial:    %#B\n", &chunk);
                }
+               if (crl->is_delta_crl(crl, &chunk))
+               {
+                       chunk = chunk_skip_zero(chunk);         
+                       fprintf(out, "  delta for: %#B\n", &chunk);
+               }
 
                /* count the number of revoked certificates */
                {
 
                /* count the number of revoked certificates */
                {
@@ -1027,9 +1110,10 @@ static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
  */
 static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
 {
  */
 static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
 {
-       bool first = TRUE;
+       bool first = TRUE, ok;
        enumerator_t *enumerator = list->create_enumerator(list);
        certificate_t *cert;
        enumerator_t *enumerator = list->create_enumerator(list);
        certificate_t *cert;
+       time_t produced, usable, now = time(NULL);
 
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
 
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
@@ -1040,13 +1124,44 @@ static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
                        fprintf(out, "\n");
                        first = FALSE;
                }
                        fprintf(out, "\n");
                        first = FALSE;
                }
-
                fprintf(out, "  signer:   \"%Y\"\n", cert->get_issuer(cert));
                fprintf(out, "  signer:   \"%Y\"\n", cert->get_issuer(cert));
+
+               /* check validity */
+               ok = cert->get_validity(cert, &now, &produced, &usable);
+               fprintf(out, "  validity:  produced at %T\n", &produced, utc);
+               fprintf(out, "             usable till %T, ", &usable, utc);
+               if (ok)
+               {
+                       fprintf(out, "ok\n");
+               }
+               else
+               {
+                       fprintf(out, "expired (%V ago)\n", &now, &usable);
+               }
        }
        enumerator->destroy(enumerator);
 }
 
 /**
        }
        enumerator->destroy(enumerator);
 }
 
 /**
+ * Print the name of an algorithm plus the name of the plugin that registered it
+ */
+static void print_alg(FILE *out, int *len, enum_name_t *alg_names, int alg_type,
+                                         const char *plugin_name)
+{
+       char alg_name[BUF_LEN];
+       int alg_name_len;
+
+       alg_name_len = sprintf(alg_name, " %N[%s]", alg_names, alg_type, plugin_name);
+       if (*len + alg_name_len > CRYPTO_MAX_ALG_LINE)
+       {
+               fprintf(out, "\n             ");
+               *len = 13;
+       }
+       fprintf(out, "%s", alg_name);
+       *len += alg_name_len;
+}
+
+/**
  * List of registered cryptographical algorithms
  */
 static void list_algs(FILE *out)
  * List of registered cryptographical algorithms
  */
 static void list_algs(FILE *out)
@@ -1057,51 +1172,125 @@ static void list_algs(FILE *out)
        hash_algorithm_t hash;
        pseudo_random_function_t prf;
        diffie_hellman_group_t group;
        hash_algorithm_t hash;
        pseudo_random_function_t prf;
        diffie_hellman_group_t group;
+       rng_quality_t quality;
+       const char *plugin_name;
+       int len;
 
        fprintf(out, "\n");
        fprintf(out, "List of registered IKEv2 Algorithms:\n");
 
        fprintf(out, "\n");
        fprintf(out, "List of registered IKEv2 Algorithms:\n");
-       fprintf(out, "\n  encryption: ");
+       fprintf(out, "\n  encryption:");
+       len = 13;
        enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
        enumerator = lib->crypto->create_crypter_enumerator(lib->crypto);
-       while (enumerator->enumerate(enumerator, &encryption))
+       while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
        {
        {
-               fprintf(out, "%N ", encryption_algorithm_names, encryption);
+               print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
        }
        enumerator->destroy(enumerator);
        }
        enumerator->destroy(enumerator);
-       fprintf(out, "\n  integrity:  ");
+       fprintf(out, "\n  integrity: ");
+       len = 13;
        enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
        enumerator = lib->crypto->create_signer_enumerator(lib->crypto);
-       while (enumerator->enumerate(enumerator, &integrity))
+       while (enumerator->enumerate(enumerator, &integrity, &plugin_name))
+       {
+               print_alg(out, &len, integrity_algorithm_names, integrity, plugin_name);
+       }
+       enumerator->destroy(enumerator);
+       fprintf(out, "\n  aead:      ");
+       len = 13;
+       enumerator = lib->crypto->create_aead_enumerator(lib->crypto);
+       while (enumerator->enumerate(enumerator, &encryption, &plugin_name))
        {
        {
-               fprintf(out, "%N ", integrity_algorithm_names, integrity);
+               print_alg(out, &len, encryption_algorithm_names, encryption, plugin_name);
        }
        enumerator->destroy(enumerator);
        }
        enumerator->destroy(enumerator);
-       fprintf(out, "\n  hasher:     ");
+       fprintf(out, "\n  hasher:    ");
+       len = 13;
        enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
        enumerator = lib->crypto->create_hasher_enumerator(lib->crypto);
-       while (enumerator->enumerate(enumerator, &hash))
+       while (enumerator->enumerate(enumerator, &hash, &plugin_name))
        {
        {
-               fprintf(out, "%N ", hash_algorithm_names, hash);
+               print_alg(out, &len, hash_algorithm_names, hash, plugin_name);
        }
        enumerator->destroy(enumerator);
        }
        enumerator->destroy(enumerator);
-       fprintf(out, "\n  prf:        ");
+       fprintf(out, "\n  prf:       ");
+       len = 13;
        enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
        enumerator = lib->crypto->create_prf_enumerator(lib->crypto);
-       while (enumerator->enumerate(enumerator, &prf))
+       while (enumerator->enumerate(enumerator, &prf, &plugin_name))
        {
        {
-               fprintf(out, "%N ", pseudo_random_function_names, prf);
+               print_alg(out, &len, pseudo_random_function_names, prf, plugin_name);
        }
        enumerator->destroy(enumerator);
        }
        enumerator->destroy(enumerator);
-       fprintf(out, "\n  dh-group:   ");
+       fprintf(out, "\n  dh-group:  ");
+       len = 13;
        enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
        enumerator = lib->crypto->create_dh_enumerator(lib->crypto);
-       while (enumerator->enumerate(enumerator, &group))
+       while (enumerator->enumerate(enumerator, &group, &plugin_name))
+       {
+               print_alg(out, &len, diffie_hellman_group_names, group, plugin_name);
+       }
+       enumerator->destroy(enumerator);
+       fprintf(out, "\n  random-gen:");
+       len = 13;
+       enumerator = lib->crypto->create_rng_enumerator(lib->crypto);
+       while (enumerator->enumerate(enumerator, &quality, &plugin_name))
        {
        {
-               fprintf(out, "%N ", diffie_hellman_group_names, group);
+               print_alg(out, &len, rng_quality_names, quality, plugin_name);
        }
        enumerator->destroy(enumerator);
        fprintf(out, "\n");
 }
 
 /**
        }
        enumerator->destroy(enumerator);
        fprintf(out, "\n");
 }
 
 /**
- * Implementation of stroke_list_t.list.
+ * List loaded plugin information
  */
  */
-static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+static void list_plugins(FILE *out)
+{
+       plugin_feature_t *features, *fp;
+       enumerator_t *enumerator;
+       linked_list_t *list;
+       plugin_t *plugin;
+       int count, i;
+       bool loaded;
+       char *str;
+
+       fprintf(out, "\n");
+       fprintf(out, "List of loaded Plugins:\n");
+       fprintf(out, "\n");
+
+       enumerator = lib->plugins->create_plugin_enumerator(lib->plugins);
+       while (enumerator->enumerate(enumerator, &plugin, &list))
+       {
+               fprintf(out, "%s:\n", plugin->get_name(plugin));
+               if (plugin->get_features)
+               {
+                       count = plugin->get_features(plugin, &features);
+                       for (i = 0; i < count; i++)
+                       {
+                               str = plugin_feature_get_string(&features[i]);
+                               switch (features[i].kind)
+                               {
+                                       case FEATURE_PROVIDE:
+                                               fp = &features[i];
+                                               loaded = list->find_first(list, NULL,
+                                                                                                 (void**)&fp) == SUCCESS;
+                                               fprintf(out, "    %s%s\n",
+                                                               str, loaded ? "" : " (not loaded)");
+                                               break;
+                                       case FEATURE_DEPENDS:
+                                               fprintf(out, "        %s\n", str);
+                                               break;
+                                       case FEATURE_SDEPEND:
+                                               fprintf(out, "        %s(soft)\n", str);
+                                               break;
+                                       default:
+                                               break;
+                               }
+                               free(str);
+                       }
+               }
+       }
+       enumerator->destroy(enumerator);
+}
+
+METHOD(stroke_list_t, list, void,
+       private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
 {
        linked_list_t *cert_list = NULL;
 
 {
        linked_list_t *cert_list = NULL;
 
@@ -1171,6 +1360,10 @@ static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
        {
                list_algs(out);
        }
        {
                list_algs(out);
        }
+       if (msg->list.flags & LIST_PLUGINS)
+       {
+               list_plugins(out);
+       }
 }
 
 /**
 }
 
 /**
@@ -1185,7 +1378,7 @@ static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
        bool on;
        int found = 0;
 
        bool on;
        int found = 0;
 
-       fprintf(out, "Leases in pool '%s', usage: %lu/%lu, %lu online\n",
+       fprintf(out, "Leases in pool '%s', usage: %u/%u, %u online\n",
                        pool, online + offline, size, online);
        enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
        while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
                        pool, online + offline, size, online);
        enumerator = this->attribute->create_lease_enumerator(this->attribute, pool);
        while (enumerator && enumerator->enumerate(enumerator, &id, &lease, &on))
@@ -1204,10 +1397,8 @@ static void pool_leases(private_stroke_list_t *this, FILE *out, char *pool,
        }
 }
 
        }
 }
 
-/**
- * Implementation of stroke_list_t.leases
- */
-static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
+METHOD(stroke_list_t, leases, void,
+       private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
 {
        enumerator_t *enumerator;
        u_int size, offline, online;
 {
        enumerator_t *enumerator;
        u_int size, offline, online;
@@ -1244,10 +1435,8 @@ static void leases(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
        DESTROY_IF(address);
 }
 
        DESTROY_IF(address);
 }
 
-/**
- * Implementation of stroke_list_t.destroy
- */
-static void destroy(private_stroke_list_t *this)
+METHOD(stroke_list_t, destroy, void,
+       private_stroke_list_t *this)
 {
        free(this);
 }
 {
        free(this);
 }
@@ -1257,15 +1446,19 @@ static void destroy(private_stroke_list_t *this)
  */
 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
 {
  */
 stroke_list_t *stroke_list_create(stroke_attribute_t *attribute)
 {
-       private_stroke_list_t *this = malloc_thing(private_stroke_list_t);
-
-       this->public.list = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))list;
-       this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status;
-       this->public.leases = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out))leases;
-       this->public.destroy = (void(*)(stroke_list_t*))destroy;
-
-       this->uptime = time_monotonic(NULL);
-       this->attribute = attribute;
+       private_stroke_list_t *this;
+
+       INIT(this,
+               .public = {
+
+                       .list = _list,
+                       .status = _status,
+                       .leases = _leases,
+                       .destroy = _destroy,
+               },
+               .uptime = time_monotonic(NULL),
+               .attribute = attribute,
+       );
 
        return &this->public;
 }
 
        return &this->public;
 }