]> git.ipfire.org Git - people/ms/strongswan.git/commitdiff
- 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

21 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_interface.c [moved from Source/charon/threads/stroke.c with 54% similarity]
Source/charon/threads/stroke_interface.h [moved from Source/charon/threads/stroke.h with 74% similarity]
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 f792c5b49404a5a31fc46af28b52b29c45555fbe..c4d65ca26d95a625f3a18423e565e40e70e90dc7 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 91521b96af9a377bf80fb2560f73ba72b2a3c3c5..9ded40f59a36e13216cf7df0dbf32e4f15b4ead6 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 1bc8057f0915cfbd394f5d1fe9693ba4d6a242f8..dcf74587c2c5b937e33533c5688c9691e29534fe 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 421dbd16a61141ed71df0c381e462198dc11cf3e..a64845e4e47625bfa7137df2dad28199e8d6f995 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 06f0e63059bece54b3668668bd3cd79abe7b72aa..4ca46063a193492e698d8874021b574a124cb98f 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 81b3e2f970e328bfcbef32912aa8a366a0c84e3f..3e8855fa9ee2062676931b2a46eecf5cfa95dabb 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 20667f736a57cba0fe44f996f07f2df1dff47f91..9c2a05cb3329cfcaf78566f82cf88b9037264aa9 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 cbdd22a84af29ffcc0943f48191f8544c5217784..89f3fff29d5266a21e98826043d345d511fd6866 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,13 +350,29 @@ 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)
 {
        return this->ike_sa_id;
 }
 
+/**
+ * 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.
  */
@@ -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 0a2661541d7936b52d170b71b6a4e3fc7909a411..16c0111f61f1443de40222d10e259fc5a5cb5979 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 ebb306a49232eba172f7c00a9e848d49af9925cf..2838d2b8ad187d63b53206a5a5ddcdb3c9138a51 100644 (file)
@@ -489,6 +489,91 @@ static status_t checkout(private_ike_sa_manager_t *this, ike_sa_id_t *ike_sa_id,
        return retval;
 }
 
+/**
+ * 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.
  */
@@ -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 5ba9e87d52844dfea02a9d17b6265ae849903196..a00f37e4fb4dab491ce829e7734fccbc18229ee6 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 6f4ceb879eeeb81a63c356ce026310b7212b9188..5062c26f7d28cd5baa1f2edf02c159cac919822f 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 55b9d048655c8b81a58f4fc852b5a48bc246e5d9..c950e0094398cd44779a5ecde2d316bbbb4f32a2 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 402ab96c4eb65fc185b862faf8aca52d06c0144d..043f547bc7ded59c90d2d5cff0b687e8995ac82d 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 $@ $<
similarity index 54%
rename from Source/charon/threads/stroke.c
rename to Source/charon/threads/stroke_interface.c
index fac2dc6fcc729f4bb09cfd4f5cc450887fc02870..5ef2737ff12cfa9b72b5589a6a5059b2ee498725 100755 (executable)
@@ -31,8 +31,9 @@
 #include <errno.h>
 #include <pthread.h>
 
-#include "stroke.h"
+#include "stroke_interface.h"
 
+#include <stroke.h>
 #include <types.h>
 #include <daemon.h>
 #include <transforms/certificate.h>
@@ -145,12 +146,17 @@ struct private_stroke_t {
        linked_list_t *private_keys;
 
        /**
-        * Assigned logger_t object.
+        * Assigned logger_t object in charon.
         */
        logger_t *logger;
+       
+       /**
+        * Logger which logs to stroke
+        */
+       logger_t *stroke_logger;
                
        /**
-        * Unix socket to use for communication
+        * Unix socket to listen for strokes
         */
        int socket;
        
@@ -260,6 +266,420 @@ static void load_private_keys(private_stroke_t *this)
        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.
  */
@@ -271,6 +691,7 @@ static void stroke_receive(private_stroke_t *this)
        int strokeaddrlen = sizeof(strokeaddr);
        ssize_t bytes_read;
        int strokefd;
+       FILE *strokefile;
        
        while (1)
        {
@@ -278,7 +699,7 @@ static void stroke_receive(private_stroke_t *this)
        
                if (strokefd < 0)
                {
-                       this->logger->log(this->logger, ERROR, "accepting stroke connection failed");
+                       this->logger->log(this->logger, ERROR, "accepting stroke connection failed: %s", strerror(errno));
                        continue;
                }
                
@@ -296,233 +717,61 @@ static void stroke_receive(private_stroke_t *this)
                bytes_read = recv(strokefd, msg, msg_length, 0);
                if (bytes_read != msg_length)
                {
-                       this->logger->log(this->logger, ERROR, "reading stroke message failed");
+                       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:
                        {
-                               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);
-                               }
+                               stroke_initiate(this, msg);
+                               break;
+                       }
+                       case STR_TERMINATE:
+                       {
+                               stroke_terminate(this, msg);
                                break;
                        }
-                       case STR_INSTALL:
+                       case STR_STATUS:
                        {
-                               pop_string(msg, &(msg->install.name));
-                               this->logger->log(this->logger, CONTROL, "received stroke: install \"%s\"", msg->install.name);
+                               stroke_status(this, msg);
                                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));
+                               stroke_add_conn(this, msg);
+                               break;
+                       }
+                       case STR_LOGTYPE:
+                       {
+                               stroke_logtype(this, msg);
+                               break;
+                       }
+                       case STR_LOGLEVEL:
+                       {
+                               stroke_loglevel(this, msg);
                                break;
                        }
-                       case STR_DEL_CONN:
                        default:
                                this->logger->log(this->logger, ERROR, "received invalid stroke");
                }
-               
+               this->stroke_logger->destroy(this->stroke_logger);
+               fclose(strokefile);
                close(strokefd);
                allocator_free(msg);
        }
@@ -657,7 +906,7 @@ static connection_t *get_connection_by_name(private_stroke_t *this, char *name)
                if (strcmp(entry->name,name) == 0)
                {
                        /* found configuration */
-                       found = entry->connection->clone(entry->connection);
+                       found = entry->connection;
                        break;
                }
        }
@@ -752,7 +1001,7 @@ static status_t get_rsa_public_key(credential_store_t *store, identification_t *
                        if (config->public_key)
                        {
                                iterator->destroy(iterator);
-                               *public_key = config->public_key;
+                               *public_key = config->public_key->clone(config->public_key);
                                return SUCCESS;
                        }
                }
@@ -780,7 +1029,7 @@ static status_t get_rsa_private_key(credential_store_t *store, identification_t
                        if (config->private_key)
                        {
                                iterator->destroy(iterator);
-                               *private_key = config->private_key;
+                               *private_key = config->private_key->clone(config->private_key);
                                return SUCCESS;
                        }
                }
similarity index 74%
rename from Source/charon/threads/stroke.h
rename to Source/charon/threads/stroke_interface.h
index 113d38d306a93d17e2bee576735bf814c749669f..ced887fa6aa8000616932ec463f2f8cf524520e8 100644 (file)
 #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;
 
index e8ee61bb23dde01cca81db923b3c2c7cc56006dd..2c8f30bf396534cc32cbf0fbcb23d26e020f43f7 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 4da3baf7caf49008a567871f63075b10e5486a30..231aee96238bf5a622ea5932fb9baa8f7fa11c2a 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 ffbe419f589f4e58a29e91d41dcaf502d75eb717..3ca760042d5534f5ad619ec8ab57379b96fb16c5 100644 (file)
@@ -125,6 +125,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.
         * 
index f5c71fc82b2b3d5d13ea967a8e0e96d17a459404..8270191a97e8205801ece8c6fc58560b890509bb 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;