- improved strokeing
authorMartin Willi <martin@strongswan.org>
Tue, 4 Apr 2006 12:45:29 +0000 (12:45 -0000)
committerMartin Willi <martin@strongswan.org>
Tue, 4 Apr 2006 12:45:29 +0000 (12:45 -0000)
- down connection
- status
- some other tweaks

23 files changed:
Source/charon/Makefile
Source/charon/asn1/der_decoder.c
Source/charon/daemon.c
Source/charon/daemon.h
Source/charon/definitions.h
Source/charon/doc/Architecture.txt
Source/charon/doc/Todo-list.txt [new file with mode: 0644]
Source/charon/sa/authenticator.c
Source/charon/sa/ike_sa.c
Source/charon/sa/ike_sa.h
Source/charon/sa/ike_sa_manager.c
Source/charon/sa/ike_sa_manager.h
Source/charon/stroke.c
Source/charon/testcases/certificate_test.c
Source/charon/threads/Makefile.threads
Source/charon/threads/stroke.c [deleted file]
Source/charon/threads/stroke.h [deleted file]
Source/charon/threads/stroke_interface.c [new file with mode: 0755]
Source/charon/threads/stroke_interface.h [new file with mode: 0644]
Source/charon/transforms/certificate.c
Source/charon/transforms/rsa/rsa_private_key.c
Source/charon/transforms/rsa/rsa_private_key.h
Source/charon/utils/logger_manager.c

index f792c5b..c4d65ca 100644 (file)
@@ -28,7 +28,7 @@ MAIN_DIR= ./
 
 LDFLAGS= -lgmp -lpthread
 
-CFLAGS+= -I. -Wall -g -DLEAK_DETECTIVE 
+CFLAGS+= -I. -O3#-Wall -g -DLEAK_DETECTIVE 
 
 # objects is extended by each included Makefile
 OBJS= 
index 91521b9..9ded40f 100644 (file)
@@ -48,7 +48,7 @@ struct private_der_decoder_t {
        asn1_rule_t *rule;
        
        /**
-        * First rule of the hole ruleset
+        * First rule of the whole ruleset
         */
        asn1_rule_t *first_rule;
        
@@ -273,6 +273,11 @@ status_t read_bitstring(private_der_decoder_t *this, chunk_t data)
        data.ptr += 1;
        data.len -= 1;
        
+       if (data.len < 1)
+       {
+               return FAILED;
+       }
+       
        chunk_t *chunk = (chunk_t*)((u_int8_t*)this->output + this->rule->data_offset);
        
        *chunk = allocator_clone_chunk(data);
@@ -302,6 +307,11 @@ u_int32_t read_length(chunk_t *data)
        u_int8_t n;
        size_t len;
        
+       if (data->len < 1)
+       {
+               return -1;
+       }
+       
        /* read first octet of length field */
        n = *data->ptr;
        data->ptr++; data->len--;
index 1bc8057..dcf7458 100644 (file)
@@ -31,7 +31,6 @@
 
 #include <types.h>
 #include <utils/allocator.h>
-#include <threads/stroke.h>
 
 
 typedef struct private_daemon_t private_daemon_t;
index 421dbd1..a64845e 100644 (file)
@@ -28,7 +28,7 @@
 #include <threads/scheduler.h>
 #include <threads/kernel_interface.h>
 #include <threads/thread_pool.h>
-#include <threads/stroke.h>
+#include <threads/stroke_interface.h>
 #include <network/socket.h>
 #include <sa/ike_sa_manager.h>
 #include <queues/send_queue.h>
index 06f0e63..4ca4606 100644 (file)
  #error "BYTE_ORDER must be defined"
 #endif
 
+/**
+ * @mainpage
+ *
+ * @section Threading Architecture
+ *
+ * All IKEv2 stuff is handled in charon. It uses a newer and more flexible
+ * architecture than pluto. Charon uses a thread-pool, which allows parallel
+ * execution SA-management. Beside the thread-pool, there are some special purpose
+ * threads which do their job for the common health of the daemon.
+   @verbatim 
+                         +------+
+                         | E  Q |
+                         | v  u |---+                   +------+  +------+
+                         | e  e |   |                   |      |  | IKE- |
+                         | n  u |  +-----------+        |      |--| SA   |
+                         | t  e |  |           |        | I  M |  +------+
+       +------------+    | -    |  | Scheduler |        | K  a |
+       |  receiver  |    +------+  |           |        | E  n |  +------+
+       +----+-------+              +-----------+        | -  a |  | IKE- |
+            |      |     +------+   |                   | S  g |--| SA   |
+    +-------+--+   +-----| J  Q |---+  +------------+   | A  e |  +------+
+   -|  socket  |         | o  u |      |            |   | -  r |
+    +-------+--+         | b  e |      |   Thread-  |   |      |
+            |            | -  u |      |   Pool     |   |      |
+       +----+-------+    |    e |------|            |---|      |
+       |   sender   |    +------+      +------------+   +------+
+       +----+-------+
+            |            +------+
+            |            | S  Q |
+            |            | e  u |
+            |            | n  e |
+            +------------| d  u |
+                         | -  e |
+                         +--+---+
+   @endverbatim
+ * The thread-pool is the heart of the architecture. It processes jobs from a
+ * (fully synchronized) job-queue. Mostly, a job is associated with a specific
+ * IKE SA. These IKE SAs are synchronized, only one thread can work one an IKE SA.
+ * This makes it unnecesary to use further synchronisation methods once a IKE SA
+ * is checked out. The (rather complex) synchronization of IKE SAs is completely
+ * done in the IKE SA manager.
+ * The sceduler is responsible for event firing. It waits until a event in the
+ * (fully synchronized) event-queue is ready for processing and pushes the event
+ * down to the job-queue. A thread form the pool will pick it up as quick as
+ * possible. Every thread can queue events or jobs. Furter, an event can place a
+ * packet in the send-queue. The sender thread waits for those packets and sends
+ * them over the wire, via the socket. The receiver does exactly the opposite of
+ * the sender. It waits on the socket, reads in packets an places them on the
+ * job-queue for further processing by a thread from the pool.
+ * There are even more threads, not drawn in the upper scheme. The stroke thread
+ * is responsible for reading and processessing commands from another process. The
+ * kernel interface thread handles communication from and to the kernel via a
+ * netlink socket. It waits for kernel events and processes them appropriately.
+ */
 
 /**
  * @defgroup config config
index 81b3e2f..3e8855f 100644 (file)
@@ -9,35 +9,35 @@ Charon uses another socket interface, called stroke. Stroke uses another
 format as whack and therefore is not compatible to whack. The starter utility,
 wich does fast configuration parsing, speaks both the protocols, whack and
 stroke. It also handles daemon startup and termination. 
-Pluto uses starter for some commans, for other it uses the whack utility. To be
+Pluto uses starter for some commands, for other it uses the whack utility. To be
 as close to pluto as possible, charon has the same split up of commands to
 starter and stroke. All commands are wrapped together in the ipsec script, which
 allows transparent control of both daemons.
 
          +-----------------------------------------+
-         ¦                  ipsec                  ¦
+         |                  ipsec                  |
          +-----+--------------+---------------+----+
-               ¦              ¦               ¦
-               ¦              ¦               ¦
-               ¦        +-----+-----+         ¦
-         +-----+----+   ¦           ¦   +-----+----+
-         ¦          ¦   ¦  starter  ¦   ¦          ¦
-         ¦  stroke  ¦   ¦           ¦   ¦   whack  ¦
-         ¦          ¦   +---+--+----+   ¦          ¦
-         +------+---+       ¦  ¦        +--+-------+
-                ¦           ¦  ¦           ¦
-            +---+------+    ¦  ¦    +------+--+
-            ¦          ¦    ¦  ¦    ¦         ¦
-            ¦  charon  +----+  +----+  pluto  ¦
-            ¦          ¦            ¦         ¦
+               |              |               |
+               |              |               |
+               |        +-----+-----+         |
+         +-----+----+   |           |   +-----+----+
+         |          |   |  starter  |   |          |
+         |  stroke  |   |           |   |   whack  |
+         |          |   +---+--+----+   |          |
+         +------+---+       |  |        +--+-------+
+                |           |  |           |
+            +---+------+    |  |    +------+--+
+            |          |    |  |    |         |
+            |  charon  +----+  +----+  pluto  |
+            |          |            |         |
             +-----+----+            +----+----+
-                  ¦                      ¦
-            +-----+----+                 ¦
-            ¦    LSF   ¦                 ¦
-            +-----+----+                 ¦
-                  ¦                      ¦
+                  |                      |
+            +-----+----+                 |
+            |    LSF   |                 |
+            +-----+----+                 |
+                  |                      |
             +-----+----+            +----+----+
-            ¦ RAW Sock ¦            ¦ UDP/500 ¦
+            | RAW Sock |            | UDP/500 |
             +----------+            +---------+
 
 Since IKEv2 uses the same port as IKEv1, both daemons must listen to UDP port
@@ -60,28 +60,28 @@ execution SA-management. Beside the thread-pool, there are some special purpose
 threads which do their job for the common health of the daemon.
 
                        +------+
-                       ¦ E  Q ¦
-                       ¦ v  u ¦---+                   +------+  +------+
-                       ¦ e  e ¦   ¦                   ¦      ¦  ¦ IKE- ¦
-                       ¦ n  u ¦  +-----------+        ¦      ¦--¦ SA   ¦
-                       ¦ t  e ¦  ¦           ¦        ¦ I  M ¦  +------+
-     +------------+    ¦ -    ¦  ¦ Scheduler ¦        ¦ K  a ¦
-     ¦  receiver  ¦    +------+  ¦           ¦        ¦ E  n ¦  +------+
-     +----+-------+              +-----------+        ¦ -  a ¦  ¦ IKE- ¦
-          ¦      ¦     +------+   ¦                   ¦ S  g ¦--¦ SA   ¦
-  +-------+--+   +-----¦ J  Q ¦---+  +------------+   ¦ A  e ¦  +------+
- -¦  socket  ¦         ¦ o  u ¦      ¦            ¦   ¦ -  r ¦
-  +-------+--+         ¦ b  e ¦      ¦   Thread-  ¦   ¦      ¦
-          ¦            ¦ -  u ¦      ¦   Pool     ¦   ¦      ¦
-     +----+-------+    ¦    e ¦------¦            ¦---¦      ¦
-     ¦   sender   ¦    +------+      +------------+   +------+
+                       | E  Q |
+                       | v  u |---+                   +------+  +------+
+                       | e  e |   |                   |      |  | IKE- |
+                       | n  u |  +-----------+        |      |--| SA   |
+                       | t  e |  |           |        | I  M |  +------+
+     +------------+    | -    |  | Scheduler |        | K  a |
+     |  receiver  |    +------+  |           |        | E  n |  +------+
+     +----+-------+              +-----------+        | -  a |  | IKE- |
+          |      |     +------+   |                   | S  g |--| SA   |
+  +-------+--+   +-----| J  Q |---+  +------------+   | A  e |  +------+
+ -|  socket  |         | o  u |      |            |   | -  r |
+  +-------+--+         | b  e |      |   Thread-  |   |      |
+          |            | -  u |      |   Pool     |   |      |
+     +----+-------+    |    e |------|            |---|      |
+     |   sender   |    +------+      +------------+   +------+
      +----+-------+
-          ¦            +------+
-          ¦            ¦ S  Q ¦
-          ¦            ¦ e  u ¦
-          ¦            ¦ n  e ¦
-          +------------¦ d  u ¦
-                       ¦ -  e ¦
+          |            +------+
+          |            | S  Q |
+          |            | e  u |
+          |            | n  e |
+          +------------| d  u |
+                       | -  e |
                        +--+---+
 
 The thread-pool is the heart of the architecture. It processes jobs from a
diff --git a/Source/charon/doc/Todo-list.txt b/Source/charon/doc/Todo-list.txt
new file mode 100644 (file)
index 0000000..91c02e8
--- /dev/null
@@ -0,0 +1,41 @@
+ TODO-List for charon
+======================
+
++ = done, - = todo, ordered by priority
+
++ private key loading: der, without passphrase
++ load all private keys from ipsec.d/private/ in stroke.c
++ handle leftcert and rightcert in starterstroke.c/stroke.c
++ load specified certs in stroke.c
++ extract public keys from certs
++ public key authentication
++ release for Andreas
+
++ stroke loglevels
++ stroke up
++ ike_sa_manager checkout_by_hosts
++ stroke down
+- stroke output redirection
+- stroke status
+
+- libx509
+  - new charon build - libstrong?
+    - transforms
+    - utils (plus host)
+  - integrate asn1 parser/oid (asn1/oid)
+  - integrate PEM loading (pem)
+  - ... (more to come, for sure)
+
+- ipsec.secrets parsing
+
+- certificate DN parsing
+- certificate subjectAltName parsing
+- certificate lookup via ID
+- certificate validation/chaining
+- certificate exchange
+
+- trapping
+
+- delete notify, when to send?
+- notifys on connection setup failure
+- create child sa message
\ No newline at end of file
index 20667f7..9c2a05c 100644 (file)
@@ -353,7 +353,8 @@ static status_t compute_auth_data (private_authenticator_t *this,
                        allocator_free_chunk(&octets);
                        if (status != SUCCESS)
                        {
-                               return status;  
+                               private_key->destroy(private_key);
+                               return status;
                        }
                        
                        *auth_payload = auth_payload_create();
index cbdd22a..89f3fff 100644 (file)
@@ -288,7 +288,7 @@ static status_t initiate_connection(private_ike_sa_t *this, connection_t *connec
        initiator_init_t *current_state;
 
        /* Work is done in state object of type INITIATOR_INIT. All other states are not 
-        * initial states and so don't have a initialize_connection function */
+        * initial states and so don't have a initiate_connection function */
        
        if (this->current_state->get_state(this->current_state) != INITIATOR_INIT)
        {
@@ -350,7 +350,7 @@ static void send_delete_ike_sa_request (private_ike_sa_t *this)
 }
 
 /**
- * Implementation of protected_ike_sa_t.get_id.
+ * Implementation of ike_sa_t.get_id.
  */
 static ike_sa_id_t* get_id(private_ike_sa_t *this)
 {
@@ -358,6 +358,22 @@ static ike_sa_id_t* get_id(private_ike_sa_t *this)
 }
 
 /**
+ * Implementation of ike_sa_t.get_my_host.
+ */
+static host_t* get_my_host(private_ike_sa_t *this)
+{
+       return this->connection->get_my_host(this->connection);;
+}
+
+/**
+ * Implementation of ike_sa_t.get_other_host.
+ */
+static host_t* get_other_host(private_ike_sa_t *this)
+{
+       return this->connection->get_other_host(this->connection);;
+}
+
+/**
  * Implementation of private_ike_sa_t.resend_last_reply.
  */
 static status_t resend_last_reply(private_ike_sa_t *this)
@@ -998,6 +1014,12 @@ static void destroy (private_ike_sa_t *this)
        }
        if (this->connection)
        {
+               host_t *me, *other;
+               me = this->connection->get_my_host(this->connection);
+               other = this->connection->get_other_host(this->connection);
+               
+               this->logger->log(this->logger, AUDIT, "IKE_SA deleted between %s - %s", 
+                                                 me->get_address(me), other->get_address(other));
                this->connection->destroy(this->connection);
        }
        if (this->policy)
@@ -1030,6 +1052,8 @@ ike_sa_t * ike_sa_create(ike_sa_id_t *ike_sa_id)
        this->protected.public.process_message = (status_t(*)(ike_sa_t*, message_t*)) process_message;
        this->protected.public.initiate_connection = (status_t(*)(ike_sa_t*,connection_t*)) initiate_connection;
        this->protected.public.get_id = (ike_sa_id_t*(*)(ike_sa_t*)) get_id;
+       this->protected.public.get_my_host = (host_t*(*)(ike_sa_t*)) get_my_host;
+       this->protected.public.get_other_host = (host_t*(*)(ike_sa_t*)) get_other_host;
        this->protected.public.retransmit_request = (status_t (*) (ike_sa_t *, u_int32_t)) retransmit_request;
        this->protected.public.get_state = (ike_sa_state_t (*) (ike_sa_t *this)) get_state;
        this->protected.public.send_delete_ike_sa_request = (void (*)(ike_sa_t*)) send_delete_ike_sa_request;
index 0a26615..16c0111 100644 (file)
@@ -120,6 +120,22 @@ struct ike_sa_t {
         * @return                              ike_sa's ike_sa_id_t
         */
        ike_sa_id_t* (*get_id) (ike_sa_t *this);
+
+       /**
+        * @brief Get local peer address of the IKE_SA.
+        *
+        * @param this                  calling object
+        * @return                              local host_t
+        */
+       host_t* (*get_my_host) (ike_sa_t *this);
+
+       /**
+        * @brief Get remote peer address of the IKE_SA.
+        *
+        * @param this                  calling object
+        * @return                              remote host_t
+        */
+       host_t* (*get_other_host) (ike_sa_t *this);
        
        /**
         * @brief Get the state of type of associated state object.
index ebb306a..2838d2b 100644 (file)
@@ -490,6 +490,91 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
 }
 
 /**
+ * Implementation of of ike_sa_manager.checkout_by_hosts.
+ */
+static status_t checkout_by_hosts(private_ike_sa_manager_t *this, host_t *me, host_t *other, ike_sa_t **ike_sa)
+{
+       iterator_t *iterator;
+       ike_sa_id_t *ike_sa_id = NULL;
+       
+       pthread_mutex_lock(&(this->mutex));
+       
+       iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               ike_sa_entry_t *current;
+               host_t *sa_me, *sa_other;
+               
+               iterator->current(iterator, (void**)&current);
+               sa_me = current->ike_sa->get_my_host(current->ike_sa);
+               sa_other = current->ike_sa->get_other_host(current->ike_sa);
+               
+               /* one end may be default/any, but not both */
+               if (me->is_default_route(me))
+               {
+                       if (other->is_default_route(other))
+                       {
+                               break;
+                       }
+                       if (other->equals(other, sa_other))
+                       {
+                               /* other matches */
+                               ike_sa_id = current->ike_sa_id;
+                       }
+               }
+               else if (other->is_default_route(other))
+               {
+                       if (me->equals(me, sa_me))
+                       {
+                               /* ME matches */
+                               ike_sa_id = current->ike_sa_id;
+                       }
+               }
+               else
+               {
+                       if (me->equals(me, sa_me) && other->equals(other, sa_other))
+                       {
+                               /* both matches */
+                               ike_sa_id = current->ike_sa_id;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       pthread_mutex_unlock(&(this->mutex));
+       
+       if (ike_sa_id)
+       {
+               /* checkout is done in the checkout function, since its rather complex */
+               return checkout(this, ike_sa_id, ike_sa);
+       }
+       return NOT_FOUND;
+}
+
+/**
+ * Implementation of ike_sa_manager_t.get_ike_sa_list.
+ */
+linked_list_t *get_ike_sa_list(private_ike_sa_manager_t* this)
+{
+       linked_list_t *list;
+       iterator_t *iterator;
+       
+       pthread_mutex_lock(&(this->mutex));
+       
+       list = linked_list_create();
+       iterator = this->ike_sa_list->create_iterator(this->ike_sa_list, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               ike_sa_entry_t *entry;
+               iterator->current(iterator, (void**)&entry);
+               list->insert_last(list, (void*)entry->ike_sa_id->clone(entry->ike_sa_id));
+       }
+       iterator->destroy(iterator);
+       
+       pthread_mutex_unlock(&(this->mutex));
+       return list;
+}
+
+/**
  * Implementation of ike_sa_manager_t.checkin.
  */
 static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
@@ -518,7 +603,7 @@ static status_t checkin(private_ike_sa_manager_t *this, ike_sa_t *ike_sa)
        else
        {
                this->logger->log(this->logger,ERROR,"Fatal Error: Tried to checkin nonexisting IKE_SA");
-               /* this SA is no more, this RELEVEL3Y should not happen */
+               /* this SA is no more, this REALLY should not happen */
                retval = NOT_FOUND;
        }
        pthread_mutex_unlock(&(this->mutex));
@@ -679,11 +764,13 @@ ike_sa_manager_t *ike_sa_manager_create()
 
        /* assign public functions */
        this->public.destroy = (void(*)(ike_sa_manager_t*))destroy;
-       this->public.create_and_checkout = (void(*)(ike_sa_manager_t*, ike_sa_t **sa))create_and_checkout;
-       this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id, ike_sa_t **sa))checkout;
-       this->public.checkin = (status_t(*)(ike_sa_manager_t*, ike_sa_t *sa))checkin;
-       this->public.delete = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t *sa_id))delete;
-       this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*, ike_sa_t *ike_sa))checkin_and_delete;
+       this->public.create_and_checkout = (void(*)(ike_sa_manager_t*,ike_sa_t**))create_and_checkout;
+       this->public.checkout = (status_t(*)(ike_sa_manager_t*, ike_sa_id_t*,ike_sa_t**))checkout;
+       this->public.checkout_by_hosts = (status_t(*)(ike_sa_manager_t*,host_t*,host_t*,ike_sa_t**))checkout_by_hosts;
+       this->public.get_ike_sa_list = (linked_list_t*(*)(ike_sa_manager_t*))get_ike_sa_list;
+       this->public.checkin = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin;
+       this->public.delete = (status_t(*)(ike_sa_manager_t*,ike_sa_id_t*))delete;
+       this->public.checkin_and_delete = (status_t(*)(ike_sa_manager_t*,ike_sa_t*))checkin_and_delete;
 
        /* initialize private functions */
        this->get_next_spi = get_next_spi;
index 5ba9e87..a00f37e 100644 (file)
@@ -78,7 +78,37 @@ struct ike_sa_manager_t {
         * @param ike_sa[out]           checked out SA
         */
        void (*create_and_checkout) (ike_sa_manager_t* ike_sa_manager,ike_sa_t **ike_sa);
+       
+       /**
+        * @brief Check out an IKE_SA, defined be the two peers.
+        * 
+        * Checking out an IKE_SA by their peer addresses may be necessary
+        * for kernel traps, status querying and so on... one of the hosts
+        * may be 0.0.0.0 (defaultroute/any), but not both.
+        * 
+        * @param ike_sa_manager        the manager object
+        * @param me                            host on local side
+        * @param other                         host on remote side
+        * @param ike_sa[out]           checked out SA
+        * @return
+        *                                                      - NOT_FOUND, if no such SA found
+        *                                                      - SUCCESS, if SA found and ike_sa set appropriatly
+        */
+       status_t (*checkout_by_hosts) (ike_sa_manager_t* ike_sa_manager, host_t *me, host_t *other, ike_sa_t **ike_sa);
+       
+       /**
+        * @brief Get a list of all IKE_SA SAs currently set up.
+        * 
+        * The resulting list with all IDs must be destroyd by 
+        * the caller. There is no guarantee an ike_sa with the 
+        * corrensponding ID really exists, since it may be deleted
+        * in the meantime by another thread.
+        * 
+        * @param ike_sa_manager        the manager object
+        * @return                                      a list with ike_sa_id_t s
+        */
+       linked_list_t *(*get_ike_sa_list) (ike_sa_manager_t* ike_sa_manager);
+       
        /**
         * @brief Checkin the SA after usage.
         * 
@@ -93,6 +123,7 @@ struct ike_sa_manager_t {
         *                                                      - NOT_FOUND when not found (shouldn't happen!)
         */
        status_t (*checkin) (ike_sa_manager_t* ike_sa_manager, ike_sa_t *ike_sa);
+       
        /**
         * @brief Delete a SA, which was not checked out.
         * 
index 6f4ceb8..5062c26 100644 (file)
  * for more details.
  */
 
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
 #include <sys/un.h>
-#include <linux/stddef.h>
+#include <sys/fcntl.h>
 #include <unistd.h>
-#include <stdlib.h>
+#include <dirent.h>
 #include <errno.h>
+#include <stdio.h>
+#include <linux/stddef.h>
 
-#include <threads/stroke.h>
+#include "stroke.h"
 
 static char* push_string(stroke_msg_t **strm, char *string)
 {
@@ -44,43 +50,51 @@ static int send_stroke_msg (stroke_msg_t *msg)
 {
        struct sockaddr_un ctl_addr = { AF_UNIX, STROKE_SOCKET };
        int sock;
+       char buffer[64];
+       int byte_count;
        
        sock = socket(AF_UNIX, SOCK_STREAM, 0);
        if (sock < 0)
        {
-               printf("Opening unix socket %s: %s\n", STROKE_SOCKET, strerror(errno));
+               fprintf(stderr, "Opening unix socket %s: %s\n", STROKE_SOCKET, strerror(errno));
                return -1;
        }
        if (connect(sock, (struct sockaddr *)&ctl_addr,
                                offsetof(struct sockaddr_un, sun_path) + strlen(ctl_addr.sun_path)) < 0)
        {
-               printf("Connect to socket failed: %s\n", strerror(errno));
+               fprintf(stderr, "Connect to socket failed: %s\n", strerror(errno));
                close(sock);
                return -1;
        }
        
-       if (dup2(sock, 1) != 1)
-       {
-               printf("Unable to redirect socket output: %s\n", strerror(errno));
-       }
-       
        /* send message */
        if (write(sock, msg, msg->length) != msg->length)
        {
-               printf("writing to socket failed: %s\n", strerror(errno));
+               fprintf(stderr, "writing to socket failed: %s\n", strerror(errno));
                close(sock);
                return -1;
        }
-
+       
+       while ((byte_count = read(sock, buffer, sizeof(buffer)-1)) > 0)
+       {
+               buffer[byte_count] = '\0';
+               printf("%s", buffer);
+       }
+       if (byte_count < 0)
+       {
+               fprintf(stderr, "reading from socket failed: %s\n", strerror(errno));
+       }
+       
        close(sock);
        return 0;
 }
 
 static int add_connection(char *name,
                                                  char *my_id, char *other_id, 
-                                                 char *my_addr, char *other_addr, 
+                                                 char *my_cert, char *other_cert,
+                                                 char *my_addr, char *other_addr,
                                                  char *my_net, char *other_net,
-                                                 u_int8_t my_netmask, u_int8_t other_netmask)
+                                                 u_int my_netmask, u_int other_netmask)
 {
        stroke_msg_t *msg = malloc(sizeof(stroke_msg_t));
        int res;
@@ -91,11 +105,13 @@ static int add_connection(char *name,
        msg->add_conn.name = push_string(&msg, name);
        
        msg->add_conn.me.id = push_string(&msg, my_id);
+       msg->add_conn.me.cert = push_string(&msg, my_cert);
        msg->add_conn.me.address = push_string(&msg, my_addr);
        msg->add_conn.me.subnet = push_string(&msg, my_net);
        msg->add_conn.me.subnet_mask = my_netmask;
        
        msg->add_conn.other.id = push_string(&msg, other_id);
+       msg->add_conn.other.cert = push_string(&msg, other_cert);
        msg->add_conn.other.address = push_string(&msg, other_addr);
        msg->add_conn.other.subnet = push_string(&msg, other_net);
        msg->add_conn.other.subnet_mask = other_netmask;
@@ -118,20 +134,171 @@ static int initiate_connection(char *name)
        return res;
 }
 
+static int terminate_connection(char *name)
+{
+       stroke_msg_t *msg = malloc(sizeof(stroke_msg_t));
+       int res;
+       
+       msg->length = sizeof(stroke_msg_t);
+       msg->type = STR_TERMINATE;
+       msg->initiate.name = push_string(&msg, name);
+       res = send_stroke_msg(msg);
+       free(msg);
+       return res;
+}
+
+static int show_status()
+{
+       stroke_msg_t *msg = malloc(sizeof(stroke_msg_t));
+       int res;
+       
+       msg->length = sizeof(stroke_msg_t);
+       msg->type = STR_STATUS;
+       res = send_stroke_msg(msg);
+       free(msg);
+       return res;
+}
+
+static int set_logtype(char *context, char *type, int enable)
+{
+       stroke_msg_t *msg = malloc(sizeof(stroke_msg_t));
+       int res;
+       
+       msg->length = sizeof(stroke_msg_t);
+       msg->type = STR_LOGTYPE;
+       msg->logtype.context = push_string(&msg, context);
+       msg->logtype.type = push_string(&msg, type);
+       msg->logtype.enable = enable;
+       res = send_stroke_msg(msg);
+       free(msg);
+       return res;
+}
+
+static int set_loglevel(char *context, u_int level)
+{
+       stroke_msg_t *msg = malloc(sizeof(stroke_msg_t));
+       int res;
+       
+       msg->length = sizeof(stroke_msg_t);
+       msg->type = STR_LOGLEVEL;
+       msg->loglevel.context = push_string(&msg, context);
+       msg->loglevel.level = level;
+       res = send_stroke_msg(msg);
+       free(msg);
+       return res;
+}
+
+static void exit_error(char *error)
+{
+       if (error)
+       {
+               fprintf(stderr, "%s\n", error);
+       }
+       exit(-1);
+}
+
+static void exit_usage(char *error)
+{
+       printf("Usage:\n");
+       printf("  Add a connection:\n");
+       printf("    stroke add NAME MY_ID OTHER_ID MY_CERT OTHER_CERT\\\n");
+       printf("           MY_ADDR OTHER_ADDR MY_NET OTHER_NET\\\n");
+       printf("           MY_NETBITS OTHER_NETBITS\n");
+       printf("    where: ID is any IKEv2 ID (currently only IPv4 adresses\n");
+       printf("           CERT is a certificate filename\n");
+       printf("           ADDR is a IPv4 address\n");
+       printf("           NET is a IPv4 address of the subnet to tunnel\n");
+       printf("           NETBITS is the size of the subnet, as the \"24\" in 192.168.0.0/24\n");
+       printf("  Initiate a connection:\n");
+       printf("    stroke up NAME\n");
+       printf("    where: NAME is a connection name added with \"stroke add\"\n");
+       printf("  Terminate a connection:\n");
+       printf("    stroke down NAME\n");
+       printf("    where: NAME is a connection name added with \"stroke add\"\n");
+       printf("  Set logtype for a logging context:\n");
+       printf("    stroke logtype CONTEXT TYPE ENABLE\n");
+       printf("    where: CONTEXT is PARSR|GNRAT|IKESA|SAMGR|CHDSA|MESSG|TPOOL|WORKR|SCHED|\n");
+       printf("                      SENDR|RECVR|SOCKT|TESTR|DAEMN|CONFG|ENCPL|PAYLD\n");
+       printf("           TYPE is CONTROL|ERROR|AUDIT|RAW|PRIVATE\n");
+       printf("           ENABLE is 0|1\n");
+       printf("  Set loglevel for a logging context:\n");
+       printf("    stroke loglevel CONTEXT LEVEL\n");
+       printf("    where: CONTEXT is PARSR|GNRAT|IKESA|SAMGR|CHDSA|MESSG|TPOOL|WORKR|SCHED|\n");
+       printf("                      SENDR|RECVR|SOCKT|TESTR|DAEMN|CONFG|ENCPL|PAYLD\n");
+       printf("           LEVEL is 0|1|2|3\n");
+       printf("  Show connection status:\n");
+       printf("    stroke status\n");
+       exit_error(error);
+}
+
 int main(int argc, char *argv[])
 {
-       add_connection("alice", NULL, NULL,
-                                  "192.168.0.1", "192.168.0.2",
-                                  "10.1.0.0", "10.2.0.0", 16, 16);
+       int res;
+       
+       if (argc < 2)
+       {
+               exit_usage(NULL);
+       }
        
-       add_connection("bob", "192.168.0.2", "192.168.0.1",
-                                  "192.168.0.2", "192.168.0.1",
-                                  "10.2.0.0", "10.1.0.0", 16, 16);
+       if (strcmp(argv[1], "status") == 0 || 
+               strcmp(argv[1], "statusall") == 0)
+       {
+               res = show_status();
+       }
        
-       if (argc == 2)
+       else if (strcmp(argv[1], "up") == 0)
+       {
+               if (argc < 3)
+               {
+                       exit_usage("\"up\" needs a connection name");
+               }
+               res = initiate_connection(argv[2]);
+       }
+       else if (strcmp(argv[1], "down") == 0)
        {
-               initiate_connection(argv[1]);
+               if (argc < 3)
+               {
+                       exit_usage("\"down\" needs a connection name");
+               }
+               res = terminate_connection(argv[2]);
+       }
+       else if (strcmp(argv[1], "add") == 0)
+       {
+               if (argc < 13)
+               {
+                       exit_usage("\"add\" needs more parameters...");
+               }
+               res = add_connection(argv[2],
+                                                        argv[3], argv[4], 
+                                                        argv[5], argv[6], 
+                                                        argv[7], argv[8], 
+                                                        argv[9], argv[10], 
+                                                        atoi(argv[11]), atoi(argv[12])); 
+       }
+       else if (strcmp(argv[1], "logtype") == 0)
+       {
+               if (argc < 5)
+               {
+                       exit_usage("\"logtype\" needs more parameters...");
+               }
+               res = set_logtype(argv[2], argv[3], atoi(argv[4])); 
+       }
+       else if (strcmp(argv[1], "loglevel") == 0)
+       {
+               if (argc < 4)
+               {
+                       exit_usage("\"logtype\" needs more parameters...");
+               }
+               res = set_loglevel(argv[2], atoi(argv[3])); 
+       }
+       else
+       {
+               exit_usage(NULL);
        }
        
+       if (res)
+       {
+               exit_error("communication with charon failed!\n");
+       }
        return 0;
 }
index 55b9d04..c950e00 100644 (file)
@@ -85,14 +85,11 @@ static char certificate_buffer[] = {
  */
 void test_certificate(protected_tester_t *tester)
 {
-       //chunk_t certificate = {certificate_buffer, sizeof(certificate_buffer)};
+       chunk_t certificate = {certificate_buffer, sizeof(certificate_buffer)};
        
-       //certificate_t *cert = certificate_create_from_chunk(certificate);
+       certificate_t *cert = certificate_create_from_chunk(certificate);
        
-       certificate_t *cert = certificate_create_from_file("myCert.der");
+       //certificate_t *cert = certificate_create_from_file("myCert.der");
        
        cert->destroy(cert);
 }
-
-
-
index 402ab96..043f547 100644 (file)
@@ -34,6 +34,6 @@ OBJS+= $(BUILD_DIR)kernel_interface.o
 $(BUILD_DIR)kernel_interface.o :$(THREADS_DIR)kernel_interface.c $(THREADS_DIR)kernel_interface.h
                                                                $(CC) $(CFLAGS) -c -o $@ $<
                                                                
-OBJS+= $(BUILD_DIR)stroke.o
-$(BUILD_DIR)stroke.o :                 $(THREADS_DIR)stroke.c $(THREADS_DIR)stroke.h
+OBJS+= $(BUILD_DIR)stroke_interface.o
+$(BUILD_DIR)stroke_interface.o :$(THREADS_DIR)stroke_interface.c $(THREADS_DIR)stroke_interface.h
                                                                $(CC) $(CFLAGS) -c -o $@ $<
diff --git a/Source/charon/threads/stroke.c b/Source/charon/threads/stroke.c
deleted file mode 100755 (executable)
index fac2dc6..0000000
+++ /dev/null
@@ -1,898 +0,0 @@
-/**
- * @file stroke.c
- * 
- * @brief Implementation of stroke_t.
- * 
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/fcntl.h>
-#include <unistd.h>
-#include <dirent.h>
-#include <errno.h>
-#include <pthread.h>
-
-#include "stroke.h"
-
-#include <types.h>
-#include <daemon.h>
-#include <transforms/certificate.h>
-#include <utils/allocator.h>
-#include <queues/jobs/initiate_ike_sa_job.h>
-
-
-struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
-
-typedef struct configuration_entry_t configuration_entry_t;
-
-/**
- * A configuration entry combines a configuration name with a connection
- * and a policy.
- * 
- * @b Constructors:
- *  - configuration_entry_create()
- */
-struct configuration_entry_t {
-       
-       /**
-        * Configuration name.
-        *
-        */
-       char *name;
-       
-       /**
-        * Configuration for IKE_SA_INIT exchange.
-        */
-       connection_t *connection;
-
-       /**
-        * Configuration for all phases after IKE_SA_INIT exchange.
-        */
-       policy_t *policy;
-       
-       /**
-        * Public key of other peer
-        */
-       rsa_public_key_t *public_key;
-       
-       /**
-        * Own private key
-        */
-       rsa_private_key_t *private_key;
-       
-       /**
-        * Destroys a configuration_entry_t
-        */
-       void (*destroy) (configuration_entry_t *this);
-};
-
-/**
- * Implementation of configuration_entry_t.destroy.
- */
-static void configuration_entry_destroy (configuration_entry_t *this)
-{
-       this->connection->destroy(this->connection);
-       this->policy->destroy(this->policy);
-       if (this->public_key)
-       {
-               this->public_key->destroy(this->public_key);
-       }
-       allocator_free(this->name);
-       allocator_free(this);
-}
-
-/**
- * Creates a configuration_entry_t object.
- */
-static configuration_entry_t * configuration_entry_create(char *name, connection_t* connection, policy_t *policy, 
-                                                                                                                 rsa_private_key_t *private_key, rsa_public_key_t *public_key)
-{
-       configuration_entry_t *entry = allocator_alloc_thing(configuration_entry_t);
-
-       /* functions */
-       entry->destroy = configuration_entry_destroy;
-
-       /* private data */
-       entry->connection = connection;
-       entry->policy = policy;
-       entry->public_key = public_key;
-       entry->private_key = private_key;
-       entry->name = allocator_alloc(strlen(name) + 1);
-       strcpy(entry->name, name);
-       
-       return entry;
-}
-
-typedef struct private_stroke_t private_stroke_t;
-
-/**
- * Private data of an stroke_t object.
- */
-struct private_stroke_t {
-
-       /**
-        * Public part of stroke_t object.
-        */
-       stroke_t public;
-
-       /**
-        * Holding all configurations.
-        */
-       linked_list_t *configurations;
-       
-       /**
-        * The list of RSA private keys accessible through crendial_store_t interface
-        */
-       linked_list_t *private_keys;
-
-       /**
-        * Assigned logger_t object.
-        */
-       logger_t *logger;
-               
-       /**
-        * Unix socket to use for communication
-        */
-       int socket;
-       
-       /**
-        * Thread which reads from the socket
-        */
-       pthread_t assigned_thread;
-
-       /**
-        * Read from the socket and handle stroke messages
-        */
-       void (*stroke_receive) (private_stroke_t *this);
-       
-       /**
-        * find a connection in the config list by name 
-        */
-       connection_t *(*get_connection_by_name) (private_stroke_t *this, char *name);
-};
-
-/**
- * Helper function which corrects the string pointers
- * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
- * contains RELATIVE addresses (relative to the beginning of the
- * stroke_msg). They must be corrected if they reach our address
- * space...
- */
-static void pop_string(stroke_msg_t *msg, char **string)
-{
-       /* check for sanity of string pointer and string */
-       if (*string == NULL)
-       {
-               *string = "";
-       }
-       else if (string < (char**)msg ||
-               string > (char**)msg + sizeof(stroke_msg_t) ||
-               *string < (char*)msg->buffer - (u_int)msg ||
-               *string > (char*)(u_int)msg->length)
-       {
-               *string = "(invalid char* in stroke msg)";
-       }
-       else
-       {
-               *string = (char*)msg + (u_int)*string;
-       }
-}
-
-/**
- * Find the private key for a public key
- */
-static rsa_private_key_t *find_private_key(private_stroke_t *this, rsa_public_key_t *public_key)
-{
-       rsa_private_key_t *private_key = NULL;
-       iterator_t *iterator;
-       
-       iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               iterator->current(iterator, (void**)&private_key);
-               if (private_key->belongs_to(private_key, public_key))
-               {
-                       break;
-               }       
-       }
-       iterator->destroy(iterator);
-       return private_key;
-}
-
-/**
- * Load all private keys form "/etc/ipsec.d/private/"
- */
-static void load_private_keys(private_stroke_t *this)
-{
-       struct dirent* entry;
-       struct stat stb;
-       DIR* dir;
-       rsa_private_key_t *key;
-       
-       /* currently only unencrypted binary DER files are loaded */
-       dir = opendir(PRIVATE_KEY_DIR);
-       if (dir == NULL || chdir(PRIVATE_KEY_DIR) == -1) {
-               this->logger->log(this->logger, ERROR, "error opening private key directory \"%s\"", PRIVATE_KEY_DIR);
-               return;
-       }
-       while ((entry = readdir(dir)) != NULL)
-       {
-               if (stat(entry->d_name, &stb) == -1)
-               {
-                       continue;
-               }
-               /* try to parse all regular files */
-               if (stb.st_mode & S_IFREG)
-               {
-                       key = rsa_private_key_create_from_file(entry->d_name, NULL);
-                       if (key)
-                       {
-                               this->private_keys->insert_last(this->private_keys, (void*)key);
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "loaded private key \"%s%s\"", 
-                                                                 PRIVATE_KEY_DIR, entry->d_name);
-                       }
-                       else
-                       {
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "private key \"%s%s\" invalid, skipped", 
-                                                                 PRIVATE_KEY_DIR, entry->d_name);
-                       }
-               }
-       }
-       closedir(dir);
-}
-
-/**
- * Implementation of private_stroke_t.stroke_receive.
- */
-static void stroke_receive(private_stroke_t *this)
-{
-       stroke_msg_t *msg;
-       u_int16_t msg_length;
-       struct sockaddr_un strokeaddr;
-       int strokeaddrlen = sizeof(strokeaddr);
-       ssize_t bytes_read;
-       int strokefd;
-       
-       while (1)
-       {
-               strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
-       
-               if (strokefd < 0)
-               {
-                       this->logger->log(this->logger, ERROR, "accepting stroke connection failed");
-                       continue;
-               }
-               
-               /* peek the length */
-               bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
-               if (bytes_read != sizeof(msg_length))
-               {
-                       this->logger->log(this->logger, ERROR, "reading lenght of stroke message failed");
-                       close(strokefd);
-                       continue;
-               }
-               
-               /* read message */
-               msg = allocator_alloc(msg_length);
-               bytes_read = recv(strokefd, msg, msg_length, 0);
-               if (bytes_read != msg_length)
-               {
-                       this->logger->log(this->logger, ERROR, "reading stroke message failed");
-                       close(strokefd);
-                       continue;
-               }
-               
-               this->logger->log_bytes(this->logger, RAW, "stroke message", (void*)msg, msg_length);
-               
-               switch (msg->type)
-               {
-                       case STR_INITIATE:
-                       {
-                               initiate_ike_sa_job_t *job;
-                               connection_t *connection;
-                               
-                               pop_string(msg, &(msg->initiate.name));
-                               this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
-                               connection = this->get_connection_by_name(this, msg->initiate.name);
-                               if (connection == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "could not find a connection named \"%s\"", msg->initiate.name);
-                               }
-                               else
-                               {
-                                       job = initiate_ike_sa_job_create(connection);
-                                       charon->job_queue->add(charon->job_queue, (job_t*)job);
-                               }
-                               break;
-                       }
-                       case STR_INSTALL:
-                       {
-                               pop_string(msg, &(msg->install.name));
-                               this->logger->log(this->logger, CONTROL, "received stroke: install \"%s\"", msg->install.name);
-                               break;
-                       }
-                       case STR_ADD_CONN:
-                       {
-                               connection_t *connection;
-                               policy_t *policy;
-                               identification_t *my_id, *other_id;
-                               host_t *my_host, *other_host, *my_subnet, *other_subnet;
-                               proposal_t *proposal;
-                               traffic_selector_t *my_ts, *other_ts;
-                               certificate_t *my_cert, *other_cert;
-                               rsa_private_key_t *private_key = NULL;
-                               rsa_public_key_t *public_key = NULL;
-                               
-                               pop_string(msg, &msg->add_conn.name);
-                               pop_string(msg, &msg->add_conn.me.address);
-                               pop_string(msg, &msg->add_conn.other.address);
-                               pop_string(msg, &msg->add_conn.me.id);
-                               pop_string(msg, &msg->add_conn.other.id);
-                               pop_string(msg, &msg->add_conn.me.cert);
-                               pop_string(msg, &msg->add_conn.other.cert);
-                               pop_string(msg, &msg->add_conn.me.subnet);
-                               pop_string(msg, &msg->add_conn.other.subnet);
-                               
-                               this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name);
-                               
-                               my_host = host_create(AF_INET, msg->add_conn.me.address, 500);
-                               if (my_host == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "received invalid host: %s", msg->add_conn.me.address);
-                                       break;
-                               }
-                               other_host = host_create(AF_INET, msg->add_conn.other.address, 500);
-                               if (other_host == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "received invalid host: %s", msg->add_conn.other.address);
-                                       my_host->destroy(my_host);
-                                       break;
-                               }
-                               my_id = identification_create_from_string(ID_IPV4_ADDR, 
-                                               *msg->add_conn.me.id ? msg->add_conn.me.id : msg->add_conn.me.address);
-                               if (my_id == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "received invalid id: %s", msg->add_conn.me.id);
-                                       my_host->destroy(my_host);
-                                       other_host->destroy(other_host);
-                                       break;
-                               }
-                               other_id = identification_create_from_string(ID_IPV4_ADDR, 
-                                               *msg->add_conn.other.id ? msg->add_conn.other.id : msg->add_conn.other.address);
-                               if (other_id == NULL)
-                               {
-                                       my_host->destroy(my_host);
-                                       other_host->destroy(other_host);
-                                       my_id->destroy(my_id);
-                                       this->logger->log(this->logger, ERROR, "received invalid id: %s", msg->add_conn.other.id);
-                                       break;
-                               }
-                               
-                               my_subnet = host_create(AF_INET, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, 500);
-                               if (my_subnet == NULL)
-                               {
-                                       my_host->destroy(my_host);
-                                       other_host->destroy(other_host);
-                                       my_id->destroy(my_id);
-                                       other_id->destroy(other_id);
-                                       this->logger->log(this->logger, ERROR, "received invalid subnet: %s", msg->add_conn.me.subnet);
-                                       break;
-                               }
-                               
-                               other_subnet = host_create(AF_INET, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, 500);
-                               if (other_subnet == NULL)
-                               {
-                                       my_host->destroy(my_host);
-                                       other_host->destroy(other_host);
-                                       my_id->destroy(my_id);
-                                       other_id->destroy(other_id);
-                                       my_subnet->destroy(my_subnet);
-                                       this->logger->log(this->logger, ERROR, "received invalid subnet: %s", msg->add_conn.me.subnet);
-                                       break;
-                               }
-                               
-                               my_ts = traffic_selector_create_from_subnet(my_subnet, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32);
-                               my_subnet->destroy(my_subnet);
-                               other_ts = traffic_selector_create_from_subnet(other_subnet, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32);
-                               other_subnet->destroy(other_subnet);
-                               
-                               if (charon->socket->is_listening_on(charon->socket, other_host))
-                               {
-                                       this->logger->log(this->logger, CONTROL|LEVEL1, "left is other host, switching");
-                                       
-                                       host_t *tmp_host = my_host;
-                                       identification_t *tmp_id = my_id;
-                                       traffic_selector_t *tmp_ts = my_ts;
-                                       char *tmp_cert = msg->add_conn.me.cert;
-                                       
-                                       my_host = other_host;
-                                       other_host = tmp_host;
-                                       my_id = other_id;
-                                       other_id = tmp_id;
-                                       my_ts = other_ts;
-                                       other_ts = tmp_ts;
-                                       msg->add_conn.me.cert = msg->add_conn.other.cert;
-                                       msg->add_conn.other.cert = tmp_cert;
-                               }
-                               else if (charon->socket->is_listening_on(charon->socket, my_host))
-                               {
-                                       this->logger->log(this->logger, CONTROL|LEVEL1, "left is own host, not switching");
-                               }
-                               else
-                               {
-                                       this->logger->log(this->logger, ERROR, "left nor right host is our, aborting");
-                                       
-                                       my_host->destroy(my_host);
-                                       other_host->destroy(other_host);
-                                       my_id->destroy(my_id);
-                                       other_id->destroy(other_id);
-                                       my_ts->destroy(my_ts);
-                                       other_ts->destroy(other_ts);
-                                       break;
-                               }
-                               
-                               connection = connection_create(my_host, other_host, my_id->clone(my_id), other_id->clone(other_id), 
-                                                                                          RSA_DIGITAL_SIGNATURE);
-                               proposal = proposal_create(1);
-                               proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-                               proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
-                               proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
-                               connection->add_proposal(connection, proposal);
-                               
-                               policy = policy_create(my_id, other_id);
-                               proposal = proposal_create(1);
-                               proposal->add_algorithm(proposal, PROTO_ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
-                               proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
-                               proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
-                               policy->add_proposal(policy, proposal);
-                               policy->add_my_traffic_selector(policy, my_ts);
-                               policy->add_other_traffic_selector(policy, other_ts);
-                               
-                               
-                               chdir(CERTIFICATE_DIR);
-                               my_cert = certificate_create_from_file(msg->add_conn.me.cert);
-                               if (my_cert == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "loading own certificate \"%s%s\" failed", 
-                                                                         CERTIFICATE_DIR, msg->add_conn.me.cert);
-                               }
-                               else
-                               {
-                                       private_key = find_private_key(this, my_cert->get_public_key(my_cert));
-                                       if (private_key)
-                                       {
-                                               this->logger->log(this->logger, CONTROL|LEVEL1, "found private key for certificate \"%s%s\"", 
-                                                                                 CERTIFICATE_DIR, msg->add_conn.me.cert);
-                                       }
-                                       else
-                                       {
-                                               this->logger->log(this->logger, ERROR, "no private key for certificate \"%s%s\" found", 
-                                                                                 CERTIFICATE_DIR, msg->add_conn.me.cert);
-                                       }
-                               }
-                               other_cert = certificate_create_from_file(msg->add_conn.other.cert);
-                               if (other_cert == NULL)
-                               {
-                                       this->logger->log(this->logger, ERROR, "loading peers certificate \"%s%s\" failed", 
-                                                                         CERTIFICATE_DIR, msg->add_conn.other.cert);
-                               }
-                               else
-                               {
-                                       public_key = other_cert->get_public_key(other_cert);
-                                       this->logger->log(this->logger, CONTROL|LEVEL1, "loaded certificate \"%s%s\" (%p)", 
-                                                                         CERTIFICATE_DIR, msg->add_conn.other.cert, public_key);
-                                       
-                               }
-                               
-                               this->configurations->insert_last(this->configurations, 
-                                               configuration_entry_create(msg->add_conn.name, connection, policy, private_key, public_key));
-                               
-                               this->logger->log(this->logger, CONTROL|LEVEL1, "connection \"%s\" added (%d in store)", 
-                                                                 msg->add_conn.name,
-                                                                 this->configurations->get_count(this->configurations));
-                               break;
-                       }
-                       case STR_DEL_CONN:
-                       default:
-                               this->logger->log(this->logger, ERROR, "received invalid stroke");
-               }
-               
-               close(strokefd);
-               allocator_free(msg);
-       }
-}
-
-/**
- * Implementation of connection_store_t.get_connection_by_hosts.
- */
-static connection_t *get_connection_by_hosts(connection_store_t *store, host_t *my_host, host_t *other_host)
-{
-       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, connections));
-       iterator_t *iterator;
-       connection_t *found = NULL;
-       
-       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", 
-                                         my_host->get_address(my_host), other_host->get_address(other_host));
-       
-       iterator = this->configurations->create_iterator(this->configurations,TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *entry;
-               host_t *config_my_host, *config_other_host;
-               
-               iterator->current(iterator,(void **) &entry);
-
-               config_my_host = entry->connection->get_my_host(entry->connection);
-               config_other_host = entry->connection->get_other_host(entry->connection);
-
-               /* first check if ip is equal */
-               if(config_other_host->ip_equals(config_other_host, other_host))
-               {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", 
-                                               config_other_host->get_address(config_other_host));
-                       /* could be right one, check my_host for default route*/
-                       if (config_my_host->is_default_route(config_my_host))
-                       {
-                               found = entry->connection->clone(entry->connection);
-                               break;
-                       }
-                       /* check now if host informations are the same */
-                       else if (config_my_host->ip_equals(config_my_host,my_host))
-                       {
-                               found = entry->connection->clone(entry->connection);
-                               break;
-                       }
-                       
-               }
-               /* Then check for wildcard hosts!
-                * TODO
-                * actually its only checked if other host with default route can be found! */
-               else if (config_other_host->is_default_route(config_other_host))
-               {
-                       /* could be right one, check my_host for default route*/
-                       if (config_my_host->is_default_route(config_my_host))
-                       {
-                               found = entry->connection->clone(entry->connection);
-                               break;
-                       }
-                       /* check now if host informations are the same */
-                       else if (config_my_host->ip_equals(config_my_host,my_host))
-                       {
-                               found = entry->connection->clone(entry->connection);
-                               break;
-                       }
-               }
-       }
-       iterator->destroy(iterator);
-       
-       /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */
-       if (found)
-       {
-               found->update_my_host(found, my_host->clone(my_host));
-               found->update_other_host(found, other_host->clone(other_host));
-       }
-       
-       return found;
-}
-
-/**
- * Implementation of connection_store_t.get_connection_by_ids.
- */
-static connection_t *get_connection_by_ids(connection_store_t *store, identification_t *my_id, identification_t *other_id)
-{
-       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, connections));
-       iterator_t *iterator;
-       connection_t *found = NULL;
-       
-       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", 
-                                         my_id->get_string(my_id), other_id->get_string(other_id));
-       
-       iterator = this->configurations->create_iterator(this->configurations,TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *entry;
-               identification_t *config_my_id, *config_other_id;
-               
-               iterator->current(iterator,(void **) &entry);
-               
-               config_my_id = entry->connection->get_my_id(entry->connection);
-               config_other_id = entry->connection->get_other_id(entry->connection);
-
-               /* first check if ids are equal 
-               * TODO: Add wildcard checks */
-               if (config_other_id->equals(config_other_id, other_id) &&
-                       config_my_id->equals(config_my_id, my_id))
-               {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", 
-                                                         config_other_id->get_string(config_other_id));
-                       found = entry->connection->clone(entry->connection);
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-       
-       return found;
-}
-
-/**
- * Implementation of private_stroke_t.get_connection_by_name.
- */
-static connection_t *get_connection_by_name(private_stroke_t *this, char *name)
-{
-       iterator_t *iterator;
-       connection_t *found = NULL;
-       
-       iterator = this->configurations->create_iterator(this->configurations, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *entry;
-               iterator->current(iterator,(void **) &entry);
-
-               if (strcmp(entry->name,name) == 0)
-               {
-                       /* found configuration */
-                       found = entry->connection->clone(entry->connection);
-                       break;
-               }
-       }
-       iterator->destroy(iterator);
-       
-       return found;
-}
-
-/**
- * Implementation of policy_store_t.get_policy.
- */
-static policy_t *get_policy(policy_store_t *store,identification_t *my_id, identification_t *other_id)
-{      
-       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, policies));
-       iterator_t *iterator;
-       policy_t *found = NULL;
-       
-       iterator = this->configurations->create_iterator(this->configurations, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *entry;
-               iterator->current(iterator,(void **) &entry);
-               identification_t *config_my_id = entry->policy->get_my_id(entry->policy);
-               identification_t *config_other_id = entry->policy->get_other_id(entry->policy);
-               
-               /* check other host first */
-               if (config_other_id->belongs_to(config_other_id, other_id))
-               {               
-                       /* get it if my_id not specified */
-                       if (my_id == NULL)
-                       {
-                               found = entry->policy->clone(entry->policy);
-                               break;
-                       }
-
-                       if (config_my_id->belongs_to(config_my_id, my_id))
-                       {
-                               found = entry->policy->clone(entry->policy);
-                               break;
-                       }
-               }
-       }
-       iterator->destroy(iterator);
-       
-       /* apply IDs as they are requsted, since they may be configured as %any or such */
-       if (found)
-       {
-               if (my_id)
-               {
-                       found->update_my_id(found, my_id->clone(my_id));
-               }
-               found->update_other_id(found, other_id->clone(other_id));
-       }
-       return found;
-}
-
-/**
- * Implementation of credential_store_t.get_shared_secret.
- */    
-static status_t get_shared_secret(credential_store_t *this, identification_t *identification, chunk_t *preshared_secret)
-{
-       char *secret = "schluessel\n";
-       preshared_secret->ptr = secret;
-       preshared_secret->len = strlen(secret) + 1;
-       
-       *preshared_secret = allocator_clone_chunk(*preshared_secret);
-       return SUCCESS;
-}
-
-/**
- * Implementation of credential_store_t.get_rsa_public_key.
- */
-static status_t get_rsa_public_key(credential_store_t *store, identification_t *identification, rsa_public_key_t **public_key)
-{
-       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
-       iterator_t *iterator;
-       
-       this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s",
-                                         identification->get_string(identification));
-       iterator = this->configurations->create_iterator(this->configurations, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *config;
-               iterator->current(iterator, (void**)&config);
-               identification_t *stored = config->policy->get_other_id(config->policy);
-               this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s",
-                                                 stored->get_string(stored));
-               if (identification->equals(identification, stored))
-               {
-                       this->logger->log(this->logger, CONTROL|LEVEL2, "found a match: %p",
-                                                         config->public_key);
-                       if (config->public_key)
-                       {
-                               iterator->destroy(iterator);
-                               *public_key = config->public_key;
-                               return SUCCESS;
-                       }
-               }
-       }
-       iterator->destroy(iterator);
-       return NOT_FOUND;
-}
-
-/**
- * Implementation of credential_store_t.get_rsa_private_key.
- */
-static status_t get_rsa_private_key(credential_store_t *store, identification_t *identification, rsa_private_key_t **private_key)
-{
-       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
-       iterator_t *iterator;
-       
-       iterator = this->configurations->create_iterator(this->configurations, TRUE);
-       while (iterator->has_next(iterator))
-       {
-               configuration_entry_t *config;
-               iterator->current(iterator, (void**)&config);
-               identification_t *stored = config->policy->get_my_id(config->policy);
-               if (identification->equals(identification, stored))
-               {
-                       if (config->private_key)
-                       {
-                               iterator->destroy(iterator);
-                               *private_key = config->private_key;
-                               return SUCCESS;
-                       }
-               }
-       }
-       iterator->destroy(iterator);
-       return NOT_FOUND;
-}
-
-/**
- * Implementation of stroke_t.destroy.
- */
-static void destroy(private_stroke_t *this)
-{
-       configuration_entry_t *entry;
-       rsa_private_key_t *priv_key;
-       
-       while (this->configurations->remove_first(this->configurations, (void **)&entry) == SUCCESS)
-       {
-               entry->destroy(entry);
-       }
-       this->configurations->destroy(this->configurations);
-       
-       while (this->private_keys->remove_first(this->private_keys, (void **)&priv_key) == SUCCESS)
-       {
-               priv_key->destroy(priv_key);
-       }
-       this->private_keys->destroy(this->private_keys);
-
-       close(this->socket);
-       unlink(socket_addr.sun_path);
-       allocator_free(this);
-}
-
-/**
- * Dummy function which does nothing.
- * Used for connection_store_t.destroy and policy_store_t.destroy,
- * since destruction is done in store_t's destructor...
- */
-void do_nothing(void *nothing)
-{
-       return;
-}
-
-/*
- * Described in header-file
- */
-stroke_t *stroke_create()
-{
-       private_stroke_t *this = allocator_alloc_thing(private_stroke_t);
-       mode_t old;
-
-       /* public functions */
-       this->public.connections.get_connection_by_ids = get_connection_by_ids;
-       this->public.connections.get_connection_by_hosts = get_connection_by_hosts;
-       this->public.connections.destroy = (void (*) (connection_store_t*))do_nothing;
-       this->public.policies.get_policy = get_policy;
-       this->public.policies.destroy = (void (*) (policy_store_t*))do_nothing;
-       this->public.credentials.get_shared_secret = (status_t (*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret;
-       this->public.credentials.get_rsa_public_key = (status_t (*)(credential_store_t*,identification_t*,rsa_public_key_t**))get_rsa_public_key;
-       this->public.credentials.get_rsa_private_key = (status_t (*)(credential_store_t*,identification_t*,rsa_private_key_t**))get_rsa_private_key;
-       this->public.credentials.destroy = (void (*) (credential_store_t*))do_nothing;
-       this->public.destroy = (void (*)(stroke_t*))destroy;
-       
-       /* private functions */
-       this->stroke_receive = stroke_receive;
-       this->get_connection_by_name = get_connection_by_name;
-       
-       this->logger = charon->logger_manager->get_logger(charon->logger_manager, CONFIG);
-       
-       /* set up unix socket */
-       this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
-       if (this->socket == -1)
-       {
-               this->logger->log(this->logger, ERROR, "could not create whack socket");
-               allocator_free(this);
-               return NULL;
-       }
-       
-       old = umask(~S_IRWXU);
-       if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
-       {
-               this->logger->log(this->logger, ERROR, "could not bind stroke socket: %s", strerror(errno));
-               close(this->socket);
-               allocator_free(this);
-               return NULL;
-       }
-       umask(old);
-       
-       if (listen(this->socket, 0) < 0)
-       {
-               this->logger->log(this->logger, ERROR, "could not listen on stroke socket: %s", strerror(errno));
-               close(this->socket);
-               unlink(socket_addr.sun_path);
-               allocator_free(this);
-               return NULL;
-       }
-       
-       /* start a thread reading from the socket */
-       if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->stroke_receive, this) != 0)
-       {
-               this->logger->log(this->logger, ERROR, "Could not spawn stroke thread");
-               close(this->socket);
-               unlink(socket_addr.sun_path);
-               allocator_free(this);
-               return NULL;
-       }
-       
-       /* private variables */
-       this->configurations = linked_list_create();
-       this->private_keys = linked_list_create();
-       
-       load_private_keys(this);
-       
-       return (&this->public);
-}
diff --git a/Source/charon/threads/stroke.h b/Source/charon/threads/stroke.h
deleted file mode 100644 (file)
index 113d38d..0000000
+++ /dev/null
@@ -1,138 +0,0 @@
-/**
- * @file stroke.h
- *
- * @brief Interface of stroke_t.
- *
- */
-
-/*
- * Copyright (C) 2006 Martin Willi
- * Hochschule fuer Technik Rapperswil
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#ifndef STROKE_H_
-#define STROKE_H_
-
-#include <config/policy_store.h>
-#include <config/connection_store.h>
-#include <config/credential_store.h>
-
-
-#define STROKE_SOCKET "/var/run/charon.ctl"
-#define IPSEC_DIR "/etc/ipsec.d/"
-#define PRIVATE_KEY_DIR IPSEC_DIR "private/"
-#define CERTIFICATE_DIR IPSEC_DIR "certs/"
-
-/**
- * @brief A stroke message sent over the unix socket.
- * 
- */
-typedef struct stroke_msg_t stroke_msg_t;
-
-struct stroke_msg_t {
-       /* length of this message with all strings */
-       u_int16_t length;
-       /* type of the message */
-       enum {
-               /* initiate a connection */
-               STR_INITIATE,
-               /* install SPD entries for a connection */
-               STR_INSTALL,
-               /* add a connection */
-               STR_ADD_CONN,
-               /* delete a connection */
-               STR_DEL_CONN,
-               /* more to come */
-       } type;
-       union {
-               /* data for STR_INITIATE, STR_INSTALL */
-               struct {
-                       char *name;
-               } initiate, install;
-               /* data for STR_ADD_CONN */
-               struct {
-                       char *name;
-                       struct {
-                               char *id;
-                               char *cert;
-                               char *address;
-                               char *subnet;
-                               u_int8_t subnet_mask;
-                       } me, other;
-               } add_conn;
-       };
-       u_int8_t buffer[];
-};
-
-
-typedef struct stroke_t stroke_t;
-
-/**
- * @brief Stroke is a configuration and control interface which
- * allows other processes to modify charons behavior.
- * 
- * stroke_t allows config manipulation (as whack in pluto). 
- * Messages of type stroke_msg_t's are sent over a unix socket
- * (/var/run/charon.ctl). stroke_t implements the connections_t
- * and the policies_t interface, which means it acts as a 
- * configuration backend for those too. stroke_t uses an own
- * thread to read from the socket.
- * 
- * @warning DO NOT cast stroke_t to any of the implemented interfaces!
- * stroke_t implements multiple interfaces, so you must use
- * stroke_t.interface_xy to access the specific interface! You have
- * been warned...
- * 
- * @todo Add clean thread cancellation
- * 
- * @b Constructors:
- * - stroke_create()
- * 
- * @ingroup threads
- */
-struct stroke_t {
-
-       /**
-        * Implements connection_store_t interface
-        */
-       connection_store_t connections;
-       
-       /**
-        * Implements policy_store_t interface
-        */
-       policy_store_t policies;
-       
-       /**
-        * Implements credential_store_t interfacce
-        */
-       credential_store_t credentials;
-       
-       /**
-        * @brief Destroy a stroke_t instance.
-        * 
-        * @param this          stroke_t objec to destroy
-        */
-       void (*destroy) (stroke_t *this);
-};
-
-
-/**
- * @brief Create the stroke interface and listen on the socket.
- * 
- * @return stroke_t object
- * 
- * @ingroup threads
- */
-stroke_t *stroke_create();
-
-#endif /* STROKE_H_ */
diff --git a/Source/charon/threads/stroke_interface.c b/Source/charon/threads/stroke_interface.c
new file mode 100755 (executable)
index 0000000..5ef2737
--- /dev/null
@@ -0,0 +1,1147 @@
+/**
+ * @file stroke.c
+ * 
+ * @brief Implementation of stroke_t.
+ * 
+ */
+
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+#include <dirent.h>
+#include <errno.h>
+#include <pthread.h>
+
+#include "stroke_interface.h"
+
+#include <stroke.h>
+#include <types.h>
+#include <daemon.h>
+#include <transforms/certificate.h>
+#include <utils/allocator.h>
+#include <queues/jobs/initiate_ike_sa_job.h>
+
+
+struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
+
+typedef struct configuration_entry_t configuration_entry_t;
+
+/**
+ * A configuration entry combines a configuration name with a connection
+ * and a policy.
+ * 
+ * @b Constructors:
+ *  - configuration_entry_create()
+ */
+struct configuration_entry_t {
+       
+       /**
+        * Configuration name.
+        *
+        */
+       char *name;
+       
+       /**
+        * Configuration for IKE_SA_INIT exchange.
+        */
+       connection_t *connection;
+
+       /**
+        * Configuration for all phases after IKE_SA_INIT exchange.
+        */
+       policy_t *policy;
+       
+       /**
+        * Public key of other peer
+        */
+       rsa_public_key_t *public_key;
+       
+       /**
+        * Own private key
+        */
+       rsa_private_key_t *private_key;
+       
+       /**
+        * Destroys a configuration_entry_t
+        */
+       void (*destroy) (configuration_entry_t *this);
+};
+
+/**
+ * Implementation of configuration_entry_t.destroy.
+ */
+static void configuration_entry_destroy (configuration_entry_t *this)
+{
+       this->connection->destroy(this->connection);
+       this->policy->destroy(this->policy);
+       if (this->public_key)
+       {
+               this->public_key->destroy(this->public_key);
+       }
+       allocator_free(this->name);
+       allocator_free(this);
+}
+
+/**
+ * Creates a configuration_entry_t object.
+ */
+static configuration_entry_t * configuration_entry_create(char *name, connection_t* connection, policy_t *policy, 
+                                                                                                                 rsa_private_key_t *private_key, rsa_public_key_t *public_key)
+{
+       configuration_entry_t *entry = allocator_alloc_thing(configuration_entry_t);
+
+       /* functions */
+       entry->destroy = configuration_entry_destroy;
+
+       /* private data */
+       entry->connection = connection;
+       entry->policy = policy;
+       entry->public_key = public_key;
+       entry->private_key = private_key;
+       entry->name = allocator_alloc(strlen(name) + 1);
+       strcpy(entry->name, name);
+       
+       return entry;
+}
+
+typedef struct private_stroke_t private_stroke_t;
+
+/**
+ * Private data of an stroke_t object.
+ */
+struct private_stroke_t {
+
+       /**
+        * Public part of stroke_t object.
+        */
+       stroke_t public;
+
+       /**
+        * Holding all configurations.
+        */
+       linked_list_t *configurations;
+       
+       /**
+        * The list of RSA private keys accessible through crendial_store_t interface
+        */
+       linked_list_t *private_keys;
+
+       /**
+        * Assigned logger_t object in charon.
+        */
+       logger_t *logger;
+       
+       /**
+        * Logger which logs to stroke
+        */
+       logger_t *stroke_logger;
+               
+       /**
+        * Unix socket to listen for strokes
+        */
+       int socket;
+       
+       /**
+        * Thread which reads from the socket
+        */
+       pthread_t assigned_thread;
+
+       /**
+        * Read from the socket and handle stroke messages
+        */
+       void (*stroke_receive) (private_stroke_t *this);
+       
+       /**
+        * find a connection in the config list by name 
+        */
+       connection_t *(*get_connection_by_name) (private_stroke_t *this, char *name);
+};
+
+/**
+ * Helper function which corrects the string pointers
+ * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
+ * contains RELATIVE addresses (relative to the beginning of the
+ * stroke_msg). They must be corrected if they reach our address
+ * space...
+ */
+static void pop_string(stroke_msg_t *msg, char **string)
+{
+       /* check for sanity of string pointer and string */
+       if (*string == NULL)
+       {
+               *string = "";
+       }
+       else if (string < (char**)msg ||
+               string > (char**)msg + sizeof(stroke_msg_t) ||
+               *string < (char*)msg->buffer - (u_int)msg ||
+               *string > (char*)(u_int)msg->length)
+       {
+               *string = "(invalid char* in stroke msg)";
+       }
+       else
+       {
+               *string = (char*)msg + (u_int)*string;
+       }
+}
+
+/**
+ * Find the private key for a public key
+ */
+static rsa_private_key_t *find_private_key(private_stroke_t *this, rsa_public_key_t *public_key)
+{
+       rsa_private_key_t *private_key = NULL;
+       iterator_t *iterator;
+       
+       iterator = this->private_keys->create_iterator(this->private_keys, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               iterator->current(iterator, (void**)&private_key);
+               if (private_key->belongs_to(private_key, public_key))
+               {
+                       break;
+               }       
+       }
+       iterator->destroy(iterator);
+       return private_key;
+}
+
+/**
+ * Load all private keys form "/etc/ipsec.d/private/"
+ */
+static void load_private_keys(private_stroke_t *this)
+{
+       struct dirent* entry;
+       struct stat stb;
+       DIR* dir;
+       rsa_private_key_t *key;
+       
+       /* currently only unencrypted binary DER files are loaded */
+       dir = opendir(PRIVATE_KEY_DIR);
+       if (dir == NULL || chdir(PRIVATE_KEY_DIR) == -1) {
+               this->logger->log(this->logger, ERROR, "error opening private key directory \"%s\"", PRIVATE_KEY_DIR);
+               return;
+       }
+       while ((entry = readdir(dir)) != NULL)
+       {
+               if (stat(entry->d_name, &stb) == -1)
+               {
+                       continue;
+               }
+               /* try to parse all regular files */
+               if (stb.st_mode & S_IFREG)
+               {
+                       key = rsa_private_key_create_from_file(entry->d_name, NULL);
+                       if (key)
+                       {
+                               this->private_keys->insert_last(this->private_keys, (void*)key);
+                               this->logger->log(this->logger, CONTROL|LEVEL1, "loaded private key \"%s%s\"", 
+                                                                 PRIVATE_KEY_DIR, entry->d_name);
+                       }
+                       else
+                       {
+                               this->logger->log(this->logger, CONTROL|LEVEL1, "private key \"%s%s\" invalid, skipped", 
+                                                                 PRIVATE_KEY_DIR, entry->d_name);
+                       }
+               }
+       }
+       closedir(dir);
+}
+
+/**
+ * Add a connection to the configuration list
+ */
+static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
+{
+       connection_t *connection;
+       policy_t *policy;
+       identification_t *my_id, *other_id;
+       host_t *my_host, *other_host, *my_subnet, *other_subnet;
+       proposal_t *proposal;
+       traffic_selector_t *my_ts, *other_ts;
+       certificate_t *my_cert, *other_cert;
+       rsa_private_key_t *private_key = NULL;
+       rsa_public_key_t *public_key = NULL;
+                               
+       pop_string(msg, &msg->add_conn.name);
+       pop_string(msg, &msg->add_conn.me.address);
+       pop_string(msg, &msg->add_conn.other.address);
+       pop_string(msg, &msg->add_conn.me.id);
+       pop_string(msg, &msg->add_conn.other.id);
+       pop_string(msg, &msg->add_conn.me.cert);
+       pop_string(msg, &msg->add_conn.other.cert);
+       pop_string(msg, &msg->add_conn.me.subnet);
+       pop_string(msg, &msg->add_conn.other.subnet);
+                               
+       this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name);
+                               
+       my_host = host_create(AF_INET, msg->add_conn.me.address, 500);
+       if (my_host == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.me.address);
+               return;
+       }
+       other_host = host_create(AF_INET, msg->add_conn.other.address, 500);
+       if (other_host == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.other.address);
+               my_host->destroy(my_host);
+               return;
+       }
+       my_id = identification_create_from_string(ID_IPV4_ADDR, 
+                                                                                         *msg->add_conn.me.id ? msg->add_conn.me.id : msg->add_conn.me.address);
+       if (my_id == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.me.id);
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               return;
+       }
+       other_id = identification_create_from_string(ID_IPV4_ADDR, 
+                       *msg->add_conn.other.id ? msg->add_conn.other.id : msg->add_conn.other.address);
+       if (other_id == NULL)
+       {
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               my_id->destroy(my_id);
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.other.id);
+               return;
+       }
+                               
+       my_subnet = host_create(AF_INET, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, 500);
+       if (my_subnet == NULL)
+       {
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               my_id->destroy(my_id);
+               other_id->destroy(other_id);
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet);
+               return;
+       }
+                               
+       other_subnet = host_create(AF_INET, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, 500);
+       if (other_subnet == NULL)
+       {
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               my_id->destroy(my_id);
+               other_id->destroy(other_id);
+               my_subnet->destroy(my_subnet);
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet);
+               return;
+       }
+                               
+       my_ts = traffic_selector_create_from_subnet(my_subnet, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32);
+       my_subnet->destroy(my_subnet);
+       other_ts = traffic_selector_create_from_subnet(other_subnet, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32);
+       other_subnet->destroy(other_subnet);
+                               
+       if (charon->socket->is_listening_on(charon->socket, other_host))
+       {
+               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching");
+                                       
+               host_t *tmp_host = my_host;
+               identification_t *tmp_id = my_id;
+               traffic_selector_t *tmp_ts = my_ts;
+               char *tmp_cert = msg->add_conn.me.cert;
+                                       
+               my_host = other_host;
+               other_host = tmp_host;
+               my_id = other_id;
+               other_id = tmp_id;
+               my_ts = other_ts;
+               other_ts = tmp_ts;
+               msg->add_conn.me.cert = msg->add_conn.other.cert;
+               msg->add_conn.other.cert = tmp_cert;
+       }
+       else if (charon->socket->is_listening_on(charon->socket, my_host))
+       {
+               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is own host, not switching");
+       }
+       else
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our, aborting");
+                                       
+               my_host->destroy(my_host);
+               other_host->destroy(other_host);
+               my_id->destroy(my_id);
+               other_id->destroy(other_id);
+               my_ts->destroy(my_ts);
+               other_ts->destroy(other_ts);
+               return;
+       }
+       
+                               
+       connection = connection_create(my_host, other_host, my_id->clone(my_id), other_id->clone(other_id), 
+                                                                  RSA_DIGITAL_SIGNATURE);
+       proposal = proposal_create(1);
+       proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
+       proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
+       proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
+       connection->add_proposal(connection, proposal);
+                               
+       policy = policy_create(my_id, other_id);
+       proposal = proposal_create(1);
+       proposal->add_algorithm(proposal, PROTO_ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
+       proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
+       proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
+       policy->add_proposal(policy, proposal);
+       policy->add_my_traffic_selector(policy, my_ts);
+       policy->add_other_traffic_selector(policy, other_ts);
+                               
+                               
+       chdir(CERTIFICATE_DIR);
+       my_cert = certificate_create_from_file(msg->add_conn.me.cert);
+       if (my_cert == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "loading own certificate \"%s%s\" failed", 
+                                                 CERTIFICATE_DIR, msg->add_conn.me.cert);
+       }
+       else
+       {
+               public_key = my_cert->get_public_key(my_cert);
+               private_key = find_private_key(this, public_key);
+               public_key->destroy(public_key);
+               if (private_key)
+               {
+                       this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "found private key for certificate \"%s%s\"", 
+                                                         CERTIFICATE_DIR, msg->add_conn.me.cert);
+               }
+               else
+               {
+                       this->stroke_logger->log(this->stroke_logger, ERROR, "no private key for certificate \"%s%s\" found", 
+                                                         CERTIFICATE_DIR, msg->add_conn.me.cert);
+               }
+               my_cert->destroy(my_cert);
+       }
+       other_cert = certificate_create_from_file(msg->add_conn.other.cert);
+       public_key = NULL;
+       if (other_cert == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "loading peers certificate \"%s%s\" failed", 
+                                                 CERTIFICATE_DIR, msg->add_conn.other.cert);
+       }
+       else
+       {
+               public_key = other_cert->get_public_key(other_cert);
+               this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "loaded certificate \"%s%s\" (%p)", 
+                                                 CERTIFICATE_DIR, msg->add_conn.other.cert, public_key);
+               other_cert->destroy(other_cert);
+       }
+                               
+       this->configurations->insert_last(this->configurations, 
+                                                                         configuration_entry_create(msg->add_conn.name, connection, policy, private_key, public_key));
+                               
+       this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "connection \"%s\" added (%d in store)", 
+                                         msg->add_conn.name,
+                                         this->configurations->get_count(this->configurations));
+}
+
+/**
+ * initiate a connection by name
+ */
+static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
+{
+       initiate_ike_sa_job_t *job;
+       connection_t *connection;
+                               
+       pop_string(msg, &(msg->initiate.name));
+       this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
+       connection = this->get_connection_by_name(this, msg->initiate.name);
+       if (connection == NULL)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "could not find a connection named \"%s\"", msg->initiate.name);
+       }
+       else
+       {
+               job = initiate_ike_sa_job_create(connection->clone(connection));
+               charon->job_queue->add(charon->job_queue, (job_t*)job);
+       }
+}
+
+/**
+ * terminate a connection by name
+ */
+static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
+{
+       connection_t *connection;
+       ike_sa_t *ike_sa;
+       host_t *my_host, *other_host;
+       status_t status;
+       
+       pop_string(msg, &(msg->terminate.name));
+       this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name);
+       connection = this->get_connection_by_name(this, msg->terminate.name);
+       
+       if (connection)
+       {
+               my_host = connection->get_my_host(connection);
+               other_host = connection->get_other_host(connection);
+               
+               status = charon->ike_sa_manager->checkout_by_hosts(charon->ike_sa_manager,
+                                                                                                 my_host, other_host, &ike_sa);
+               
+               if (status == SUCCESS)
+               {
+                       this->stroke_logger->log(this->stroke_logger, CONTROL, "deleting IKE SA between %s - %s",
+                                                       my_host->get_address(my_host), other_host->get_address(other_host));
+               
+                       charon->ike_sa_manager->checkin_and_delete(charon->ike_sa_manager, ike_sa);
+               }
+               else
+               {
+                       this->stroke_logger->log(this->stroke_logger, ERROR, "no active connection found between %s - %s",
+                                                         my_host->get_address(my_host), other_host->get_address(other_host));
+               }
+       }
+       else
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "could not find a connection named \"%s\"", msg->terminate.name);
+       }
+       
+}
+
+/**
+ * show status of (established) connections
+ */
+static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
+{
+       linked_list_t *list;
+       iterator_t *iterator;
+       status_t status;
+       
+       
+       list = charon->ike_sa_manager->get_ike_sa_list(charon->ike_sa_manager);
+       iterator = list->create_iterator(list, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               ike_sa_id_t *ike_sa_id;
+               ike_sa_t *ike_sa;
+               iterator->current(iterator, (void**)&ike_sa_id);
+               
+               status = charon->ike_sa_manager->checkout(charon->ike_sa_manager, ike_sa_id, &ike_sa);
+               if (status == SUCCESS)
+               {
+                       host_t *me, *other;
+                       me = ike_sa->get_my_host(ike_sa);
+                       other = ike_sa->get_other_host(ike_sa);
+                       
+                       
+                       this->stroke_logger->log(this->stroke_logger, CONTROL, "IKE SA in state %s as %s",
+                                                                        mapping_find(ike_sa_state_m, ike_sa->get_state(ike_sa)),
+                                                                        ike_sa_id->is_initiator ? "initiator" : "responder");
+                       
+                       this->stroke_logger->log(this->stroke_logger, CONTROL, " SPIs: %15lld - %-15lld",
+                                                                        ike_sa_id->get_initiator_spi(ike_sa_id),
+                                                                        ike_sa_id->get_responder_spi(ike_sa_id));
+                       
+
+                       this->stroke_logger->log(this->stroke_logger, CONTROL, " Addr: %15s - %-15s",
+                                                                        me->get_address(me), other->get_address(other));
+                                               
+                       charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
+               }
+               
+               ike_sa_id->destroy(ike_sa_id);
+       }
+       iterator->destroy(iterator);
+       list->destroy(list);
+}
+
+logger_context_t get_context(char *context)
+{
+       if      (strcasecmp(context, "ALL") == 0) return ALL_LOGGERS;
+       else if (strcasecmp(context, "PARSR") == 0) return PARSER;
+       else if (strcasecmp(context, "GNRAT") == 0) return GENERATOR;
+       else if (strcasecmp(context, "IKESA") == 0) return IKE_SA;
+       else if (strcasecmp(context, "SAMGR") == 0) return IKE_SA_MANAGER;
+       else if (strcasecmp(context, "CHDSA") == 0) return CHILD_SA;
+       else if (strcasecmp(context, "MESSG") == 0) return MESSAGE;
+       else if (strcasecmp(context, "TPOOL") == 0) return THREAD_POOL;
+       else if (strcasecmp(context, "WORKR") == 0) return WORKER;
+       else if (strcasecmp(context, "SCHED") == 0) return SCHEDULER;
+       else if (strcasecmp(context, "SENDR") == 0) return SENDER;
+       else if (strcasecmp(context, "RECVR") == 0) return RECEIVER;
+       else if (strcasecmp(context, "SOCKT") == 0) return SOCKET;
+       else if (strcasecmp(context, "TESTR") == 0) return TESTER;
+       else if (strcasecmp(context, "DAEMN") == 0) return DAEMON;
+       else if (strcasecmp(context, "CONFG") == 0) return CONFIG;
+       else if (strcasecmp(context, "ENCPL") == 0) return ENCRYPTION_PAYLOAD;
+       else if (strcasecmp(context, "PAYLD") == 0) return PAYLOAD;
+       else return -2;
+}
+
+/**
+ * set the type of logged messages in a context
+ */
+static void stroke_logtype(private_stroke_t *this, stroke_msg_t *msg)
+{
+       pop_string(msg, &(msg->logtype.context));
+       pop_string(msg, &(msg->logtype.type));
+       
+       this->logger->log(this->logger, CONTROL, "received stroke: logtype for %s", msg->logtype.context);
+       
+       log_level_t level;
+       logger_context_t context = get_context(msg->logtype.context);
+       if (context == -2)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->logtype.context);
+               return;
+       }
+       
+       if      (strcasecmp(msg->logtype.type, "CONTROL") == 0) level = CONTROL;
+       else if (strcasecmp(msg->logtype.type, "ERROR") == 0) level = ERROR;
+       else if (strcasecmp(msg->logtype.type, "AUDIT") == 0) level = AUDIT;
+       else if (strcasecmp(msg->logtype.type, "RAW") == 0) level = RAW;
+       else if (strcasecmp(msg->logtype.type, "PRIVATE") == 0) level = PRIVATE;
+       else
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid type (%s)!", msg->logtype.type);
+               return;
+       }
+       
+       if (msg->logtype.enable)
+       {
+               charon->logger_manager->enable_log_level(charon->logger_manager,
+                                                                                                context, level);
+       }
+       else
+       {
+               charon->logger_manager->disable_log_level(charon->logger_manager,
+                               context, level);
+       }
+}
+
+/**
+ * set the verbosity of a logger
+ */
+static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
+{
+       pop_string(msg, &(msg->loglevel.context));
+       
+       this->logger->log(this->logger, CONTROL, "received stroke: log_level for %s", msg->loglevel.context);
+       
+       log_level_t level;
+       logger_context_t context = get_context(msg->loglevel.context);
+       
+       if (context == -2)
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->loglevel.context);
+               return;
+       }
+       
+       if (msg->loglevel.level == 0)
+       {
+               level = LEVEL0;
+       }
+       else if (msg->loglevel.level == 1)
+       {
+               level = LEVEL1;
+       }
+       else if (msg->loglevel.level == 2)
+       {
+               level = LEVEL2;
+       }
+       else if (msg->loglevel.level == 3)
+       {
+               level = LEVEL3;
+       }
+       else 
+       {
+               this->stroke_logger->log(this->stroke_logger, ERROR, "invalid level (%d)!", msg->loglevel.level);
+               return;
+       }
+       
+       charon->logger_manager->enable_log_level(charon->logger_manager, context, level);
+}
+
+/**
+ * Implementation of private_stroke_t.stroke_receive.
+ */
+static void stroke_receive(private_stroke_t *this)
+{
+       stroke_msg_t *msg;
+       u_int16_t msg_length;
+       struct sockaddr_un strokeaddr;
+       int strokeaddrlen = sizeof(strokeaddr);
+       ssize_t bytes_read;
+       int strokefd;
+       FILE *strokefile;
+       
+       while (1)
+       {
+               strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
+       
+               if (strokefd < 0)
+               {
+                       this->logger->log(this->logger, ERROR, "accepting stroke connection failed: %s", strerror(errno));
+                       continue;
+               }
+               
+               /* peek the length */
+               bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
+               if (bytes_read != sizeof(msg_length))
+               {
+                       this->logger->log(this->logger, ERROR, "reading lenght of stroke message failed");
+                       close(strokefd);
+                       continue;
+               }
+               
+               /* read message */
+               msg = allocator_alloc(msg_length);
+               bytes_read = recv(strokefd, msg, msg_length, 0);
+               if (bytes_read != msg_length)
+               {
+                       this->logger->log(this->logger, ERROR, "reading stroke message failed: %s");
+                       close(strokefd);
+                       continue;
+               }
+               
+               strokefile = fdopen(dup(strokefd), "w");
+               if (strokefile == NULL)
+               {
+                       this->logger->log(this->logger, ERROR, "opening stroke output channel failed:", strerror(errno));
+                       close(strokefd);
+                       allocator_free(msg);
+                       continue;
+               }
+               
+               this->stroke_logger = logger_create("-", CONTROL|ERROR, FALSE, strokefile);
+               
+               this->logger->log_bytes(this->logger, RAW, "stroke message", (void*)msg, msg_length);
+               
+               switch (msg->type)
+               {
+                       case STR_INITIATE:
+                       {
+                               stroke_initiate(this, msg);
+                               break;
+                       }
+                       case STR_TERMINATE:
+                       {
+                               stroke_terminate(this, msg);
+                               break;
+                       }
+                       case STR_STATUS:
+                       {
+                               stroke_status(this, msg);
+                               break;
+                       }
+                       case STR_ADD_CONN:
+                       {
+                               stroke_add_conn(this, msg);
+                               break;
+                       }
+                       case STR_LOGTYPE:
+                       {
+                               stroke_logtype(this, msg);
+                               break;
+                       }
+                       case STR_LOGLEVEL:
+                       {
+                               stroke_loglevel(this, msg);
+                               break;
+                       }
+                       default:
+                               this->logger->log(this->logger, ERROR, "received invalid stroke");
+               }
+               this->stroke_logger->destroy(this->stroke_logger);
+               fclose(strokefile);
+               close(strokefd);
+               allocator_free(msg);
+       }
+}
+
+/**
+ * Implementation of connection_store_t.get_connection_by_hosts.
+ */
+static connection_t *get_connection_by_hosts(connection_store_t *store, host_t *my_host, host_t *other_host)
+{
+       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, connections));
+       iterator_t *iterator;
+       connection_t *found = NULL;
+       
+       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for hosts %s - %s", 
+                                         my_host->get_address(my_host), other_host->get_address(other_host));
+       
+       iterator = this->configurations->create_iterator(this->configurations,TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *entry;
+               host_t *config_my_host, *config_other_host;
+               
+               iterator->current(iterator,(void **) &entry);
+
+               config_my_host = entry->connection->get_my_host(entry->connection);
+               config_other_host = entry->connection->get_other_host(entry->connection);
+
+               /* first check if ip is equal */
+               if(config_other_host->ip_equals(config_other_host, other_host))
+               {
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote host %s", 
+                                               config_other_host->get_address(config_other_host));
+                       /* could be right one, check my_host for default route*/
+                       if (config_my_host->is_default_route(config_my_host))
+                       {
+                               found = entry->connection->clone(entry->connection);
+                               break;
+                       }
+                       /* check now if host informations are the same */
+                       else if (config_my_host->ip_equals(config_my_host,my_host))
+                       {
+                               found = entry->connection->clone(entry->connection);
+                               break;
+                       }
+                       
+               }
+               /* Then check for wildcard hosts!
+                * TODO
+                * actually its only checked if other host with default route can be found! */
+               else if (config_other_host->is_default_route(config_other_host))
+               {
+                       /* could be right one, check my_host for default route*/
+                       if (config_my_host->is_default_route(config_my_host))
+                       {
+                               found = entry->connection->clone(entry->connection);
+                               break;
+                       }
+                       /* check now if host informations are the same */
+                       else if (config_my_host->ip_equals(config_my_host,my_host))
+                       {
+                               found = entry->connection->clone(entry->connection);
+                               break;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       
+       /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */
+       if (found)
+       {
+               found->update_my_host(found, my_host->clone(my_host));
+               found->update_other_host(found, other_host->clone(other_host));
+       }
+       
+       return found;
+}
+
+/**
+ * Implementation of connection_store_t.get_connection_by_ids.
+ */
+static connection_t *get_connection_by_ids(connection_store_t *store, identification_t *my_id, identification_t *other_id)
+{
+       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, connections));
+       iterator_t *iterator;
+       connection_t *found = NULL;
+       
+       this->logger->log(this->logger, CONTROL|LEVEL1, "getting config for ids %s - %s", 
+                                         my_id->get_string(my_id), other_id->get_string(other_id));
+       
+       iterator = this->configurations->create_iterator(this->configurations,TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *entry;
+               identification_t *config_my_id, *config_other_id;
+               
+               iterator->current(iterator,(void **) &entry);
+               
+               config_my_id = entry->connection->get_my_id(entry->connection);
+               config_other_id = entry->connection->get_other_id(entry->connection);
+
+               /* first check if ids are equal 
+               * TODO: Add wildcard checks */
+               if (config_other_id->equals(config_other_id, other_id) &&
+                       config_my_id->equals(config_my_id, my_id))
+               {
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "config entry with remote id %s", 
+                                                         config_other_id->get_string(config_other_id));
+                       found = entry->connection->clone(entry->connection);
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
+       
+       return found;
+}
+
+/**
+ * Implementation of private_stroke_t.get_connection_by_name.
+ */
+static connection_t *get_connection_by_name(private_stroke_t *this, char *name)
+{
+       iterator_t *iterator;
+       connection_t *found = NULL;
+       
+       iterator = this->configurations->create_iterator(this->configurations, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *entry;
+               iterator->current(iterator,(void **) &entry);
+
+               if (strcmp(entry->name,name) == 0)
+               {
+                       /* found configuration */
+                       found = entry->connection;
+                       break;
+               }
+       }
+       iterator->destroy(iterator);
+       
+       return found;
+}
+
+/**
+ * Implementation of policy_store_t.get_policy.
+ */
+static policy_t *get_policy(policy_store_t *store,identification_t *my_id, identification_t *other_id)
+{      
+       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, policies));
+       iterator_t *iterator;
+       policy_t *found = NULL;
+       
+       iterator = this->configurations->create_iterator(this->configurations, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *entry;
+               iterator->current(iterator,(void **) &entry);
+               identification_t *config_my_id = entry->policy->get_my_id(entry->policy);
+               identification_t *config_other_id = entry->policy->get_other_id(entry->policy);
+               
+               /* check other host first */
+               if (config_other_id->belongs_to(config_other_id, other_id))
+               {               
+                       /* get it if my_id not specified */
+                       if (my_id == NULL)
+                       {
+                               found = entry->policy->clone(entry->policy);
+                               break;
+                       }
+
+                       if (config_my_id->belongs_to(config_my_id, my_id))
+                       {
+                               found = entry->policy->clone(entry->policy);
+                               break;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       
+       /* apply IDs as they are requsted, since they may be configured as %any or such */
+       if (found)
+       {
+               if (my_id)
+               {
+                       found->update_my_id(found, my_id->clone(my_id));
+               }
+               found->update_other_id(found, other_id->clone(other_id));
+       }
+       return found;
+}
+
+/**
+ * Implementation of credential_store_t.get_shared_secret.
+ */    
+static status_t get_shared_secret(credential_store_t *this, identification_t *identification, chunk_t *preshared_secret)
+{
+       char *secret = "schluessel\n";
+       preshared_secret->ptr = secret;
+       preshared_secret->len = strlen(secret) + 1;
+       
+       *preshared_secret = allocator_clone_chunk(*preshared_secret);
+       return SUCCESS;
+}
+
+/**
+ * Implementation of credential_store_t.get_rsa_public_key.
+ */
+static status_t get_rsa_public_key(credential_store_t *store, identification_t *identification, rsa_public_key_t **public_key)
+{
+       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
+       iterator_t *iterator;
+       
+       this->logger->log(this->logger, CONTROL|LEVEL2, "Looking for public key for %s",
+                                         identification->get_string(identification));
+       iterator = this->configurations->create_iterator(this->configurations, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *config;
+               iterator->current(iterator, (void**)&config);
+               identification_t *stored = config->policy->get_other_id(config->policy);
+               this->logger->log(this->logger, CONTROL|LEVEL2, "there is one for %s",
+                                                 stored->get_string(stored));
+               if (identification->equals(identification, stored))
+               {
+                       this->logger->log(this->logger, CONTROL|LEVEL2, "found a match: %p",
+                                                         config->public_key);
+                       if (config->public_key)
+                       {
+                               iterator->destroy(iterator);
+                               *public_key = config->public_key->clone(config->public_key);
+                               return SUCCESS;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       return NOT_FOUND;
+}
+
+/**
+ * Implementation of credential_store_t.get_rsa_private_key.
+ */
+static status_t get_rsa_private_key(credential_store_t *store, identification_t *identification, rsa_private_key_t **private_key)
+{
+       private_stroke_t *this = (private_stroke_t*)((u_int8_t*)store - offsetof(stroke_t, credentials));
+       iterator_t *iterator;
+       
+       iterator = this->configurations->create_iterator(this->configurations, TRUE);
+       while (iterator->has_next(iterator))
+       {
+               configuration_entry_t *config;
+               iterator->current(iterator, (void**)&config);
+               identification_t *stored = config->policy->get_my_id(config->policy);
+               if (identification->equals(identification, stored))
+               {
+                       if (config->private_key)
+                       {
+                               iterator->destroy(iterator);
+                               *private_key = config->private_key->clone(config->private_key);
+                               return SUCCESS;
+                       }
+               }
+       }
+       iterator->destroy(iterator);
+       return NOT_FOUND;
+}
+
+/**
+ * Implementation of stroke_t.destroy.
+ */
+static void destroy(private_stroke_t *this)
+{
+       configuration_entry_t *entry;
+       rsa_private_key_t *priv_key;
+       
+       while (this->configurations->remove_first(this->configurations, (void **)&entry) == SUCCESS)
+       {
+               entry->destroy(entry);
+       }
+       this->configurations->destroy(this->configurations);
+       
+       while (this->private_keys->remove_first(this->private_keys, (void **)&priv_key) == SUCCESS)
+       {
+               priv_key->destroy(priv_key);
+       }
+       this->private_keys->destroy(this->private_keys);
+
+       close(this->socket);
+       unlink(socket_addr.sun_path);
+       allocator_free(this);
+}
+
+/**
+ * Dummy function which does nothing.
+ * Used for connection_store_t.destroy and policy_store_t.destroy,
+ * since destruction is done in store_t's destructor...
+ */
+void do_nothing(void *nothing)
+{
+       return;
+}
+
+/*
+ * Described in header-file
+ */
+stroke_t *stroke_create()
+{
+       private_stroke_t *this = allocator_alloc_thing(private_stroke_t);
+       mode_t old;
+
+       /* public functions */
+       this->public.connections.get_connection_by_ids = get_connection_by_ids;
+       this->public.connections.get_connection_by_hosts = get_connection_by_hosts;
+       this->public.connections.destroy = (void (*) (connection_store_t*))do_nothing;
+       this->public.policies.get_policy = get_policy;
+       this->public.policies.destroy = (void (*) (policy_store_t*))do_nothing;
+       this->public.credentials.get_shared_secret = (status_t (*)(credential_store_t*,identification_t*,chunk_t*))get_shared_secret;
+       this->public.credentials.get_rsa_public_key = (status_t (*)(credential_store_t*,identification_t*,rsa_public_key_t**))get_rsa_public_key;
+       this->public.credentials.get_rsa_private_key = (status_t (*)(credential_store_t*,identification_t*,rsa_private_key_t**))get_rsa_private_key;
+       this->public.credentials.destroy = (void (*) (credential_store_t*))do_nothing;
+       this->public.destroy = (void (*)(stroke_t*))destroy;
+       
+       /* private functions */
+       this->stroke_receive = stroke_receive;
+       this->get_connection_by_name = get_connection_by_name;
+       
+       this->logger = charon->logger_manager->get_logger(charon->logger_manager, CONFIG);
+       
+       /* set up unix socket */
+       this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
+       if (this->socket == -1)
+       {
+               this->logger->log(this->logger, ERROR, "could not create whack socket");
+               allocator_free(this);
+               return NULL;
+       }
+       
+       old = umask(~S_IRWXU);
+       if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
+       {
+               this->logger->log(this->logger, ERROR, "could not bind stroke socket: %s", strerror(errno));
+               close(this->socket);
+               allocator_free(this);
+               return NULL;
+       }
+       umask(old);
+       
+       if (listen(this->socket, 0) < 0)
+       {
+               this->logger->log(this->logger, ERROR, "could not listen on stroke socket: %s", strerror(errno));
+               close(this->socket);
+               unlink(socket_addr.sun_path);
+               allocator_free(this);
+               return NULL;
+       }
+       
+       /* start a thread reading from the socket */
+       if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->stroke_receive, this) != 0)
+       {
+               this->logger->log(this->logger, ERROR, "Could not spawn stroke thread");
+               close(this->socket);
+               unlink(socket_addr.sun_path);
+               allocator_free(this);
+               return NULL;
+       }
+       
+       /* private variables */
+       this->configurations = linked_list_create();
+       this->private_keys = linked_list_create();
+       
+       load_private_keys(this);
+       
+       return (&this->public);
+}
diff --git a/Source/charon/threads/stroke_interface.h b/Source/charon/threads/stroke_interface.h
new file mode 100644 (file)
index 0000000..ced887f
--- /dev/null
@@ -0,0 +1,96 @@
+/**
+ * @file stroke.h
+ *
+ * @brief Interface of stroke_t.
+ *
+ */
+
+/*
+ * Copyright (C) 2006 Martin Willi
+ * Hochschule fuer Technik Rapperswil
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#ifndef STROKE_H_
+#define STROKE_H_
+
+#include <config/policy_store.h>
+#include <config/connection_store.h>
+#include <config/credential_store.h>
+
+
+#define IPSEC_DIR "/etc/ipsec.d/"
+#define PRIVATE_KEY_DIR IPSEC_DIR "private/"
+#define CERTIFICATE_DIR IPSEC_DIR "certs/"
+
+
+typedef struct stroke_t stroke_t;
+
+/**
+ * @brief Stroke is a configuration and control interface which
+ * allows other processes to modify charons behavior.
+ * 
+ * stroke_t allows config manipulation (as whack in pluto). 
+ * Messages of type stroke_msg_t's are sent over a unix socket
+ * (/var/run/charon.ctl). stroke_t implements the connections_t
+ * and the policies_t interface, which means it acts as a 
+ * configuration backend for those too. stroke_t uses an own
+ * thread to read from the socket.
+ * 
+ * @warning DO NOT cast stroke_t to any of the implemented interfaces!
+ * stroke_t implements multiple interfaces, so you must use
+ * stroke_t.interface_xy to access the specific interface! You have
+ * been warned...
+ * 
+ * @todo Add clean thread cancellation
+ * 
+ * @b Constructors:
+ * - stroke_create()
+ * 
+ * @ingroup threads
+ */
+struct stroke_t {
+
+       /**
+        * Implements connection_store_t interface
+        */
+       connection_store_t connections;
+       
+       /**
+        * Implements policy_store_t interface
+        */
+       policy_store_t policies;
+       
+       /**
+        * Implements credential_store_t interfacce
+        */
+       credential_store_t credentials;
+       
+       /**
+        * @brief Destroy a stroke_t instance.
+        * 
+        * @param this          stroke_t objec to destroy
+        */
+       void (*destroy) (stroke_t *this);
+};
+
+
+/**
+ * @brief Create the stroke interface and listen on the socket.
+ * 
+ * @return stroke_t object
+ * 
+ * @ingroup threads
+ */
+stroke_t *stroke_create();
+
+#endif /* STROKE_H_ */
index e8ee61b..2c8f30b 100755 (executable)
@@ -145,7 +145,6 @@ static rsa_public_key_t *get_public_key(private_certificate_t *this)
        return this->public_key->clone(this->public_key);
 }
 
-
 /**
  * Implementation of certificate.destroy.
  */
index 4da3baf..231aee9 100644 (file)
@@ -155,6 +155,8 @@ static asn1_rule_t rsa_private_key_rules[] = {
        {ASN1_END, 0, 0, 0},
 };
 
+static private_rsa_private_key_t *rsa_private_key_create_empty();
+
 /**
  * Implementation of private_rsa_private_key_t.compute_prime.
  */
@@ -389,6 +391,25 @@ bool belongs_to(private_rsa_private_key_t *this, rsa_public_key_t *public)
        return FALSE;
 }
 
+/**
+ * Implementation of rsa_private_key.clone.
+ */
+static rsa_private_key_t* _clone(private_rsa_private_key_t *this)
+{
+       private_rsa_private_key_t *clone = rsa_private_key_create_empty();
+       
+       mpz_init_set(clone->n, this->n);
+       mpz_init_set(clone->e, this->e);
+       mpz_init_set(clone->p, this->p);
+       mpz_init_set(clone->q, this->q);
+       mpz_init_set(clone->d, this->d);
+       mpz_init_set(clone->exp1, this->exp1);
+       mpz_init_set(clone->exp2, this->exp2);
+       mpz_init_set(clone->coeff, this->coeff);
+       clone->k = this->k;
+       
+       return &clone->public;
+}
 
 /**
  * Implementation of rsa_private_key.destroy.
@@ -419,6 +440,7 @@ static private_rsa_private_key_t *rsa_private_key_create_empty()
        this->public.save_key = (status_t (*) (rsa_private_key_t*,char*))save_key;
        this->public.get_public_key = (rsa_public_key_t *(*) (rsa_private_key_t*))get_public_key;
        this->public.belongs_to = (bool (*) (rsa_private_key_t*,rsa_public_key_t*))belongs_to;
+       this->public.clone = (rsa_private_key_t*(*)(rsa_private_key_t*))_clone;
        this->public.destroy = (void (*) (rsa_private_key_t*))destroy;
        
        /* private functions */
index ffbe419..3ca7600 100644 (file)
@@ -126,6 +126,14 @@ struct rsa_private_key_t {
        bool (*belongs_to) (rsa_private_key_t *this, rsa_public_key_t *public);
        
        /**
+        * @brief Clone the private key.
+        * 
+        * @param this                          private key to clone
+        * @return                                      clone of this
+        */
+       rsa_private_key_t *(*clone) (rsa_private_key_t *this);
+       
+       /**
         * @brief Destroys the private key.
         * 
         * @param this                          private key to destroy
index f5c71fc..8270191 100644 (file)
@@ -54,31 +54,33 @@ mapping_t logger_context_t_mappings[] = {
        {MAPPING_END, NULL},
 };
 
+#define DEFAULT_OUTPUT NULL
+
 struct {
        char *name;
        log_level_t level;
        bool log_thread_ids;
        FILE *output;
 } logger_defaults[] = {
-       { "PARSR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* PARSER */
-       { "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* GENERATOR */
-       { "IKESA", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* IKE_SA */
-       { "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* IKE_SA_MANAGER */
-       { "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* CHILD_SA */
-       { "MESSG", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* MESSAGE */
-       { "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* THREAD_POOL */
-       { "WORKR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* WORKER */
-       { "SCHED", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* SCHEDULER */
-       { "SENDR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* SENDER */
-       { "RECVR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* RECEIVER */
-       { "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* SOCKET */
-       { "TESTR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* TESTER */
-       { "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, NULL}, /* DAEMON */
-       { "CONFG", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* CONFIG */
-       { "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* ENCRYPTION_PAYLOAD */
-       { "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* PAYLOAD */
-       { "DERDC", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* DER_DECODER */
-       { "DEREC", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  NULL}, /* DER_ENCODER */
+       { "PARSR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* PARSER */
+       { "GNRAT", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* GENERATOR */
+       { "IKESA", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* IKE_SA */
+       { "SAMGR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* IKE_SA_MANAGER */
+       { "CHDSA", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* CHILD_SA */
+       { "MESSG", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* MESSAGE */
+       { "TPOOL", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* THREAD_POOL */
+       { "WORKR", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* WORKER */
+       { "SCHED", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* SCHEDULER */
+       { "SENDR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* SENDER */
+       { "RECVR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* RECEIVER */
+       { "SOCKT", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* SOCKET */
+       { "TESTR", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* TESTER */
+       { "DAEMN", ERROR|CONTROL|AUDIT|LEVEL0,  FALSE, DEFAULT_OUTPUT}, /* DAEMON */
+       { "CONFG", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* CONFIG */
+       { "ENCPL", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* ENCRYPTION_PAYLOAD */
+       { "PAYLD", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* PAYLOAD */
+       { "DERDC", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* DER_DECODER */
+       { "DEREC", ERROR|CONTROL|AUDIT|LEVEL0,  TRUE,  DEFAULT_OUTPUT}, /* DER_ENCODER */
 };
 
 
@@ -202,7 +204,7 @@ logger_manager_t *logger_manager_create(log_level_t default_log_level)
        for (i = 0; i < LOGGER_CONTEXT_ROOF; i++)
        {
                this->loggers[i] = logger_create(logger_defaults[i].name, logger_defaults[i].level, 
-                                                                                logger_defaults[i].log_thread_ids, logger_defaults[i].output);
+                                                                                logger_defaults[i].log_thread_ids, stdout);//logger_defaults[i].output);
        }
        
        return &this->public;