minimal stroke_list_ocsp() implementation
[strongswan.git] / src / charon / plugins / stroke / stroke_list.c
index 5ce02d9..024e95b 100644 (file)
@@ -18,6 +18,7 @@
 #include "stroke_list.h"
 
 #include <daemon.h>
+#include <utils/linked_list.h>
 #include <credentials/certificates/x509.h>
 #include <credentials/certificates/crl.h>
 
@@ -36,6 +37,11 @@ struct private_stroke_list_t {
         * public functions
         */
        stroke_list_t public;
+       
+       /**
+        * timestamp of daemon start
+        */
+       time_t uptime;
 };
 
 /**
@@ -178,12 +184,15 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
        child_cfg_t *child_cfg;
        ike_sa_t *ike_sa;
        char *name = NULL;
+       time_t uptime;
        
        name = msg->status.name;
        
        if (all)
        {
+               uptime = time(NULL) - this->uptime;
                fprintf(out, "Performance:\n");
+               fprintf(out, "  uptime: %V, since %#T\n", &uptime, &this->uptime, FALSE);
                fprintf(out, "  worker threads: %d idle of %d,",
                                charon->processor->get_idle_threads(charon->processor),
                                charon->processor->get_total_threads(charon->processor));
@@ -266,17 +275,64 @@ static void status(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out, bo
 }
 
 /**
+ * create a unique certificate list without duplicates
+ * certicates having the same issuer are grouped together.
+ */
+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);
+       certificate_t *cert;
+       
+       while (enumerator->enumerate(enumerator, (void**)&cert))
+       {
+               iterator_t *iterator = list->create_iterator(list, TRUE);
+               identification_t *issuer = cert->get_issuer(cert);
+               bool previous_same, same = FALSE, last = TRUE;
+               certificate_t *list_cert;
+               
+               while (iterator->iterate(iterator, (void**)&list_cert))
+               {
+                       /* exit if we have a duplicate? */
+                       if (list_cert == cert)
+                       {
+                               last = FALSE;
+                               break;
+                       }
+                       /* group certificates with same issuer */
+                       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;
+                               break;
+                       }
+               }
+               iterator->destroy(iterator);
+
+               if (last)
+               {
+                       list->insert_last(list, (void *)cert->get_ref(cert));
+               }
+       }
+       enumerator->destroy(enumerator);
+       return list;
+}
+
+/**
  * list all X.509 certificates matching the flags
  */
-static void stroke_list_certs(char *label, x509_flag_t flags, bool utc, FILE *out)
+static void stroke_list_certs(linked_list_t *list, char *label, 
+                                                         x509_flag_t flags, bool utc, FILE *out)
 {
        bool first = TRUE;
        time_t now = time(NULL);
+       enumerator_t *enumerator = list->create_enumerator(list);
        certificate_t *cert;
-       enumerator_t *enumerator;
-       
-       enumerator = charon->credentials->create_cert_enumerator(
-                                               charon->credentials, CERT_X509, KEY_ANY, NULL, FALSE);
+
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
                x509_t *x509 = (x509_t*)cert;
@@ -322,8 +378,8 @@ static void stroke_list_certs(char *label, x509_flag_t flags, bool utc, FILE *ou
                        }
                        enumerator->destroy(enumerator);
 
-                       fprintf(out, "  subject:  %D\n", cert->get_subject(cert));
-                       fprintf(out, "  issuer:   %D\n", cert->get_issuer(cert));
+                       fprintf(out, "  subject:  \"%D\"\n", cert->get_subject(cert));
+                       fprintf(out, "  issuer:   \"%D\"\n", cert->get_issuer(cert));
                        fprintf(out, "  serial:    %#B\n", &serial);
 
                        /* list validity */
@@ -385,17 +441,23 @@ static void stroke_list_certs(char *label, x509_flag_t flags, bool utc, FILE *ou
 }
 
 /**
+ * list all X.509 attribute certificates
+ */
+static void stroke_list_acerts(bool utc, FILE *out)
+{
+
+}
+
+/**
  * list all X.509 CRLs
  */
-static void stroke_list_crls(bool utc, FILE *out)
+static void stroke_list_crls(linked_list_t *list, bool utc, FILE *out)
 {
        bool first = TRUE;
        time_t thisUpdate, nextUpdate, now = time(NULL);
+       enumerator_t *enumerator = list->create_enumerator(list);
        certificate_t *cert;
-       enumerator_t *enumerator;
        
-       enumerator = charon->credentials->create_cert_enumerator(
-                                               charon->credentials, CERT_X509_CRL, KEY_ANY, NULL, FALSE);
        while (enumerator->enumerate(enumerator, (void**)&cert))
        {
                crl_t *crl = (crl_t*)cert;
@@ -410,7 +472,7 @@ static void stroke_list_crls(bool utc, FILE *out)
                }
                fprintf(out, "\n");
 
-               fprintf(out, "  issuer:   %D\n", cert->get_issuer(cert));
+               fprintf(out, "  issuer:   \"%D\"\n", cert->get_issuer(cert));
 
                /* list optional crlNumber */
                if (serial.ptr)
@@ -460,42 +522,80 @@ static void stroke_list_crls(bool utc, FILE *out)
 }
 
 /**
+ * list all OCSP responses
+ */
+static void stroke_list_ocsp(linked_list_t* list, bool utc, FILE *out)
+{
+       bool first = TRUE;
+       time_t thisUpdate, nextUpdate, now = time(NULL);
+       enumerator_t *enumerator = list->create_enumerator(list);
+       certificate_t *cert;
+       
+       while (enumerator->enumerate(enumerator, (void**)&cert))
+       {
+               if (first)
+               {
+                       fprintf(out, "\n");
+                       fprintf(out, "List of OCSP responses:\n");
+                       fprintf(out, "\n");
+                       first = FALSE;
+               }
+
+               fprintf(out, "  signer:   \"%D\"\n", cert->get_issuer(cert));
+       }
+       enumerator->destroy(enumerator);
+}
+
+/**
  * Implementation of stroke_list_t.list.
  */
 static void list(private_stroke_list_t *this, stroke_msg_t *msg, FILE *out)
 {
+       linked_list_t *cert_list = NULL;
+
+       if (msg->list.flags & (LIST_CERTS | LIST_CACERTS | LIST_OCSPCERTS | LIST_AACERTS))
+       {
+               cert_list = create_unique_cert_list(CERT_X509);
+       }
        if (msg->list.flags & LIST_CERTS)
        {
-               stroke_list_certs("X.509 End Entity Certificates",
+               stroke_list_certs(cert_list, "X.509 End Entity Certificates",
                                                  0, msg->list.utc, out);
        }
        if (msg->list.flags & LIST_CACERTS)
        {
-               stroke_list_certs("X.509 CA Certificates",
+               stroke_list_certs(cert_list, "X.509 CA Certificates",
                                                  X509_CA, msg->list.utc, out);
        }
        if (msg->list.flags & LIST_OCSPCERTS)
        {
-               stroke_list_certs("X.509 OCSP Signer Certificates",
+               stroke_list_certs(cert_list, "X.509 OCSP Signer Certificates",
                                                  X509_OCSP_SIGNER, msg->list.utc, out);
        }
        if (msg->list.flags & LIST_AACERTS)
        {
-               stroke_list_certs("X.509 AA Certificates",
+               stroke_list_certs(cert_list, "X.509 AA Certificates",
                                                  X509_AA, msg->list.utc, out);
        }
        if (msg->list.flags & LIST_ACERTS)
        {
-
+               stroke_list_acerts(msg->list.utc, out);
        }
        if (msg->list.flags & LIST_CRLS)
        {
-               stroke_list_crls(msg->list.utc, out);
+               linked_list_t *crl_list = create_unique_cert_list(CERT_X509_CRL);
+
+               stroke_list_crls(crl_list, msg->list.utc, out);
+               crl_list->destroy_offset(crl_list, offsetof(certificate_t, destroy)); 
        }
        if (msg->list.flags & LIST_OCSP)
        {
+               linked_list_t *ocsp_list = create_unique_cert_list(CERT_X509_OCSP_RESPONSE);
 
+               stroke_list_ocsp(ocsp_list, msg->list.utc, out);
+               ocsp_list->destroy_offset(ocsp_list, offsetof(certificate_t, destroy)); 
        }
+       DESTROY_OFFSET_IF(cert_list, offsetof(certificate_t, destroy));
 }
 
 /**
@@ -517,6 +617,8 @@ stroke_list_t *stroke_list_create()
        this->public.status = (void(*)(stroke_list_t*, stroke_msg_t *msg, FILE *out,bool))status;
        this->public.destroy = (void(*)(stroke_list_t*))destroy;
        
+       this->uptime = time(NULL);
+       
        return &this->public;
 }