4 * @brief Implementation of stroke_t.
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 #include <sys/types.h>
26 #include <sys/socket.h>
28 #include <sys/fcntl.h>
34 #include "stroke_interface.h"
39 #include <crypto/x509.h>
40 #include <queues/jobs/initiate_ike_sa_job.h>
43 struct sockaddr_un socket_addr
= { AF_UNIX
, STROKE_SOCKET
};
45 typedef struct configuration_entry_t configuration_entry_t
;
48 * A configuration entry combines a configuration name with a connection
52 * - configuration_entry_create()
54 struct configuration_entry_t
{
63 * Configuration for IKE_SA_INIT exchange.
65 connection_t
*connection
;
68 * Configuration for all phases after IKE_SA_INIT exchange.
73 * Public key of other peer
75 rsa_public_key_t
*public_key
;
80 rsa_private_key_t
*private_key
;
83 * Destroys a configuration_entry_t
85 void (*destroy
) (configuration_entry_t
*this);
89 * Implementation of configuration_entry_t.destroy.
91 static void configuration_entry_destroy (configuration_entry_t
*this)
93 this->connection
->destroy(this->connection
);
94 this->policy
->destroy(this->policy
);
97 this->public_key
->destroy(this->public_key
);
104 * Creates a configuration_entry_t object.
106 static configuration_entry_t
* configuration_entry_create(char *name
, connection_t
* connection
, policy_t
*policy
,
107 rsa_private_key_t
*private_key
, rsa_public_key_t
*public_key
)
109 configuration_entry_t
*entry
= malloc_thing(configuration_entry_t
);
112 entry
->destroy
= configuration_entry_destroy
;
115 entry
->connection
= connection
;
116 entry
->policy
= policy
;
117 entry
->public_key
= public_key
;
118 entry
->private_key
= private_key
;
119 entry
->name
= malloc(strlen(name
) + 1);
120 strcpy(entry
->name
, name
);
125 typedef struct private_stroke_t private_stroke_t
;
128 * Private data of an stroke_t object.
130 struct private_stroke_t
{
133 * Public part of stroke_t object.
138 * Holding all configurations.
140 linked_list_t
*configurations
;
143 * The list of RSA private keys accessible through crendial_store_t interface
145 linked_list_t
*private_keys
;
148 * Assigned logger_t object in charon.
153 * Logger which logs to stroke
155 logger_t
*stroke_logger
;
158 * Unix socket to listen for strokes
163 * Thread which reads from the socket
165 pthread_t assigned_thread
;
168 * Read from the socket and handle stroke messages
170 void (*stroke_receive
) (private_stroke_t
*this);
173 * find a connection in the config list by name
175 connection_t
*(*get_connection_by_name
) (private_stroke_t
*this, char *name
);
179 * Helper function which corrects the string pointers
180 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
181 * contains RELATIVE addresses (relative to the beginning of the
182 * stroke_msg). They must be corrected if they reach our address
185 static void pop_string(stroke_msg_t
*msg
, char **string
)
187 /* check for sanity of string pointer and string */
192 else if (string
< (char**)msg
||
193 string
> (char**)msg
+ sizeof(stroke_msg_t
) ||
194 *string
< (char*)msg
->buffer
- (u_int
)msg
||
195 *string
> (char*)(u_int
)msg
->length
)
197 *string
= "(invalid char* in stroke msg)";
201 *string
= (char*)msg
+ (u_int
)*string
;
206 * Find the private key for a public key
208 static rsa_private_key_t
*find_private_key(private_stroke_t
*this, rsa_public_key_t
*public_key
)
210 rsa_private_key_t
*private_key
= NULL
;
211 iterator_t
*iterator
;
213 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Looking up private key by public key...");
215 iterator
= this->private_keys
->create_iterator(this->private_keys
, TRUE
);
216 while (iterator
->has_next(iterator
))
218 iterator
->current(iterator
, (void**)&private_key
);
219 if (private_key
->belongs_to(private_key
, public_key
))
221 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "found a match");
224 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "this one did not match");
226 iterator
->destroy(iterator
);
231 * Load all private keys form "/etc/ipsec.d/private/"
233 static void load_private_keys(private_stroke_t
*this)
235 struct dirent
* entry
;
238 rsa_private_key_t
*key
;
240 /* currently only unencrypted binary DER files are loaded */
241 dir
= opendir(PRIVATE_KEY_DIR
);
242 if (dir
== NULL
|| chdir(PRIVATE_KEY_DIR
) == -1) {
243 this->logger
->log(this->logger
, ERROR
, "error opening private key directory \"%s\"", PRIVATE_KEY_DIR
);
246 while ((entry
= readdir(dir
)) != NULL
)
248 if (stat(entry
->d_name
, &stb
) == -1)
252 /* try to parse all regular files */
253 if (stb
.st_mode
& S_IFREG
)
255 key
= rsa_private_key_create_from_file(entry
->d_name
, NULL
);
258 this->private_keys
->insert_last(this->private_keys
, (void*)key
);
259 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "loaded private key \"%s%s\"",
260 PRIVATE_KEY_DIR
, entry
->d_name
);
264 this->logger
->log(this->logger
, ERROR
, "private key \"%s%s\" invalid, skipped",
265 PRIVATE_KEY_DIR
, entry
->d_name
);
273 * Add a connection to the configuration list
275 static void stroke_add_conn(private_stroke_t
*this, stroke_msg_t
*msg
)
277 connection_t
*connection
;
279 identification_t
*my_id
, *other_id
;
280 host_t
*my_host
, *other_host
, *my_subnet
, *other_subnet
;
281 proposal_t
*proposal
;
282 traffic_selector_t
*my_ts
, *other_ts
;
283 x509_t
*my_cert
, *other_cert
;
284 rsa_private_key_t
*private_key
= NULL
;
285 rsa_public_key_t
*public_key
= NULL
;
287 pop_string(msg
, &msg
->add_conn
.name
);
288 pop_string(msg
, &msg
->add_conn
.me
.address
);
289 pop_string(msg
, &msg
->add_conn
.other
.address
);
290 pop_string(msg
, &msg
->add_conn
.me
.id
);
291 pop_string(msg
, &msg
->add_conn
.other
.id
);
292 pop_string(msg
, &msg
->add_conn
.me
.cert
);
293 pop_string(msg
, &msg
->add_conn
.other
.cert
);
294 pop_string(msg
, &msg
->add_conn
.me
.subnet
);
295 pop_string(msg
, &msg
->add_conn
.other
.subnet
);
297 this->logger
->log(this->logger
, CONTROL
, "received stroke: add connection \"%s\"", msg
->add_conn
.name
);
299 my_host
= host_create(AF_INET
, msg
->add_conn
.me
.address
, 500);
302 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid host: %s", msg
->add_conn
.me
.address
);
305 other_host
= host_create(AF_INET
, msg
->add_conn
.other
.address
, 500);
306 if (other_host
== NULL
)
308 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid host: %s", msg
->add_conn
.other
.address
);
309 my_host
->destroy(my_host
);
312 my_id
= identification_create_from_string(*msg
->add_conn
.me
.id
?
313 msg
->add_conn
.me
.id
: msg
->add_conn
.me
.address
);
316 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid id: %s", msg
->add_conn
.me
.id
);
317 my_host
->destroy(my_host
);
318 other_host
->destroy(other_host
);
321 other_id
= identification_create_from_string(*msg
->add_conn
.other
.id
?
322 msg
->add_conn
.other
.id
: msg
->add_conn
.other
.address
);
323 if (other_id
== NULL
)
325 my_host
->destroy(my_host
);
326 other_host
->destroy(other_host
);
327 my_id
->destroy(my_id
);
328 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid id: %s", msg
->add_conn
.other
.id
);
332 my_subnet
= host_create(AF_INET
, *msg
->add_conn
.me
.subnet
? msg
->add_conn
.me
.subnet
: msg
->add_conn
.me
.address
, 500);
333 if (my_subnet
== NULL
)
335 my_host
->destroy(my_host
);
336 other_host
->destroy(other_host
);
337 my_id
->destroy(my_id
);
338 other_id
->destroy(other_id
);
339 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid subnet: %s", msg
->add_conn
.me
.subnet
);
343 other_subnet
= host_create(AF_INET
, *msg
->add_conn
.other
.subnet
? msg
->add_conn
.other
.subnet
: msg
->add_conn
.other
.address
, 500);
344 if (other_subnet
== NULL
)
346 my_host
->destroy(my_host
);
347 other_host
->destroy(other_host
);
348 my_id
->destroy(my_id
);
349 other_id
->destroy(other_id
);
350 my_subnet
->destroy(my_subnet
);
351 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid subnet: %s", msg
->add_conn
.me
.subnet
);
355 my_ts
= traffic_selector_create_from_subnet(my_subnet
, *msg
->add_conn
.me
.subnet
? msg
->add_conn
.me
.subnet_mask
: 32);
356 my_subnet
->destroy(my_subnet
);
357 other_ts
= traffic_selector_create_from_subnet(other_subnet
, *msg
->add_conn
.other
.subnet
? msg
->add_conn
.other
.subnet_mask
: 32);
358 other_subnet
->destroy(other_subnet
);
360 if (charon
->socket
->is_listening_on(charon
->socket
, other_host
))
362 this->stroke_logger
->log(this->stroke_logger
, CONTROL
|LEVEL1
, "left is other host, switching");
364 host_t
*tmp_host
= my_host
;
365 identification_t
*tmp_id
= my_id
;
366 traffic_selector_t
*tmp_ts
= my_ts
;
367 char *tmp_cert
= msg
->add_conn
.me
.cert
;
369 my_host
= other_host
;
370 other_host
= tmp_host
;
375 msg
->add_conn
.me
.cert
= msg
->add_conn
.other
.cert
;
376 msg
->add_conn
.other
.cert
= tmp_cert
;
378 else if (charon
->socket
->is_listening_on(charon
->socket
, my_host
))
380 this->stroke_logger
->log(this->stroke_logger
, CONTROL
|LEVEL1
, "left is own host, not switching");
384 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "left nor right host is our, aborting");
386 my_host
->destroy(my_host
);
387 other_host
->destroy(other_host
);
388 my_id
->destroy(my_id
);
389 other_id
->destroy(other_id
);
390 my_ts
->destroy(my_ts
);
391 other_ts
->destroy(other_ts
);
396 connection
= connection_create(my_host
, other_host
, my_id
->clone(my_id
), other_id
->clone(other_id
),
397 RSA_DIGITAL_SIGNATURE
);
398 proposal
= proposal_create(1);
399 proposal
->add_algorithm(proposal
, PROTO_IKE
, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 16);
400 proposal
->add_algorithm(proposal
, PROTO_IKE
, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA1_96
, 0);
401 proposal
->add_algorithm(proposal
, PROTO_IKE
, INTEGRITY_ALGORITHM
, AUTH_HMAC_MD5_96
, 0);
402 proposal
->add_algorithm(proposal
, PROTO_IKE
, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_SHA1
, 0);
403 proposal
->add_algorithm(proposal
, PROTO_IKE
, PSEUDO_RANDOM_FUNCTION
, PRF_HMAC_MD5
, 0);
404 proposal
->add_algorithm(proposal
, PROTO_IKE
, DIFFIE_HELLMAN_GROUP
, MODP_2048_BIT
, 0);
405 proposal
->add_algorithm(proposal
, PROTO_IKE
, DIFFIE_HELLMAN_GROUP
, MODP_1536_BIT
, 0);
406 proposal
->add_algorithm(proposal
, PROTO_IKE
, DIFFIE_HELLMAN_GROUP
, MODP_1024_BIT
, 0);
407 proposal
->add_algorithm(proposal
, PROTO_IKE
, DIFFIE_HELLMAN_GROUP
, MODP_4096_BIT
, 0);
408 proposal
->add_algorithm(proposal
, PROTO_IKE
, DIFFIE_HELLMAN_GROUP
, MODP_8192_BIT
, 0);
409 connection
->add_proposal(connection
, proposal
);
411 policy
= policy_create(my_id
, other_id
);
412 proposal
= proposal_create(1);
413 proposal
->add_algorithm(proposal
, PROTO_ESP
, ENCRYPTION_ALGORITHM
, ENCR_AES_CBC
, 16);
414 proposal
->add_algorithm(proposal
, PROTO_ESP
, INTEGRITY_ALGORITHM
, AUTH_HMAC_SHA1_96
, 0);
415 proposal
->add_algorithm(proposal
, PROTO_ESP
, INTEGRITY_ALGORITHM
, AUTH_HMAC_MD5_96
, 0);
416 policy
->add_proposal(policy
, proposal
);
417 policy
->add_my_traffic_selector(policy
, my_ts
);
418 policy
->add_other_traffic_selector(policy
, other_ts
);
421 chdir(CERTIFICATE_DIR
);
422 my_cert
= x509_create_from_file(msg
->add_conn
.me
.cert
);
425 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "loading own certificate \"%s%s\" failed",
426 CERTIFICATE_DIR
, msg
->add_conn
.me
.cert
);
430 public_key
= my_cert
->get_public_key(my_cert
);
431 private_key
= find_private_key(this, public_key
);
432 public_key
->destroy(public_key
);
435 this->stroke_logger
->log(this->stroke_logger
, CONTROL
|LEVEL1
, "found private key for certificate \"%s%s\"",
436 CERTIFICATE_DIR
, msg
->add_conn
.me
.cert
);
440 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "no private key for certificate \"%s%s\" found",
441 CERTIFICATE_DIR
, msg
->add_conn
.me
.cert
);
443 my_cert
->destroy(my_cert
);
445 other_cert
= x509_create_from_file(msg
->add_conn
.other
.cert
);
447 if (other_cert
== NULL
)
449 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "loading peers certificate \"%s%s\" failed",
450 CERTIFICATE_DIR
, msg
->add_conn
.other
.cert
);
454 public_key
= other_cert
->get_public_key(other_cert
);
455 this->stroke_logger
->log(this->stroke_logger
, CONTROL
|LEVEL1
, "loaded certificate \"%s%s\" (%p)",
456 CERTIFICATE_DIR
, msg
->add_conn
.other
.cert
, public_key
);
457 other_cert
->destroy(other_cert
);
460 this->configurations
->insert_last(this->configurations
,
461 configuration_entry_create(msg
->add_conn
.name
, connection
, policy
, private_key
, public_key
));
463 this->stroke_logger
->log(this->stroke_logger
, CONTROL
|LEVEL1
, "connection \"%s\" added (%d in store)",
465 this->configurations
->get_count(this->configurations
));
469 * initiate a connection by name
471 static void stroke_initiate(private_stroke_t
*this, stroke_msg_t
*msg
)
473 initiate_ike_sa_job_t
*job
;
474 connection_t
*connection
;
476 pop_string(msg
, &(msg
->initiate
.name
));
477 this->logger
->log(this->logger
, CONTROL
, "received stroke: initiate \"%s\"", msg
->initiate
.name
);
478 connection
= this->get_connection_by_name(this, msg
->initiate
.name
);
479 if (connection
== NULL
)
481 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "could not find a connection named \"%s\"", msg
->initiate
.name
);
485 job
= initiate_ike_sa_job_create(connection
->clone(connection
));
486 charon
->job_queue
->add(charon
->job_queue
, (job_t
*)job
);
491 * terminate a connection by name
493 static void stroke_terminate(private_stroke_t
*this, stroke_msg_t
*msg
)
495 connection_t
*connection
;
497 host_t
*my_host
, *other_host
;
500 pop_string(msg
, &(msg
->terminate
.name
));
501 this->logger
->log(this->logger
, CONTROL
, "received stroke: terminate \"%s\"", msg
->terminate
.name
);
502 connection
= this->get_connection_by_name(this, msg
->terminate
.name
);
506 my_host
= connection
->get_my_host(connection
);
507 other_host
= connection
->get_other_host(connection
);
509 status
= charon
->ike_sa_manager
->checkout_by_hosts(charon
->ike_sa_manager
,
510 my_host
, other_host
, &ike_sa
);
512 if (status
== SUCCESS
)
514 this->stroke_logger
->log(this->stroke_logger
, CONTROL
, "deleting IKE SA between %s - %s",
515 my_host
->get_address(my_host
), other_host
->get_address(other_host
));
517 charon
->ike_sa_manager
->checkin_and_delete(charon
->ike_sa_manager
, ike_sa
);
521 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "no active connection found between %s - %s",
522 my_host
->get_address(my_host
), other_host
->get_address(other_host
));
527 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "could not find a connection named \"%s\"", msg
->terminate
.name
);
533 * show status of (established) connections
535 static void stroke_status(private_stroke_t
*this, stroke_msg_t
*msg
)
538 iterator_t
*iterator
;
542 list
= charon
->ike_sa_manager
->get_ike_sa_list(charon
->ike_sa_manager
);
543 iterator
= list
->create_iterator(list
, TRUE
);
544 while (iterator
->has_next(iterator
))
546 ike_sa_id_t
*ike_sa_id
;
548 iterator
->current(iterator
, (void**)&ike_sa_id
);
550 status
= charon
->ike_sa_manager
->checkout(charon
->ike_sa_manager
, ike_sa_id
, &ike_sa
);
551 if (status
== SUCCESS
)
554 me
= ike_sa
->get_my_host(ike_sa
);
555 other
= ike_sa
->get_other_host(ike_sa
);
558 this->stroke_logger
->log(this->stroke_logger
, CONTROL
, "IKE SA in state %s as %s",
559 mapping_find(ike_sa_state_m
, ike_sa
->get_state(ike_sa
)),
560 ike_sa_id
->is_initiator
? "initiator" : "responder");
562 this->stroke_logger
->log(this->stroke_logger
, CONTROL
, " SPIs: %15lld - %-15lld",
563 ike_sa_id
->get_initiator_spi(ike_sa_id
),
564 ike_sa_id
->get_responder_spi(ike_sa_id
));
567 this->stroke_logger
->log(this->stroke_logger
, CONTROL
, " Addr: %15s - %-15s",
568 me
->get_address(me
), other
->get_address(other
));
570 charon
->ike_sa_manager
->checkin(charon
->ike_sa_manager
, ike_sa
);
573 ike_sa_id
->destroy(ike_sa_id
);
575 iterator
->destroy(iterator
);
579 logger_context_t
get_context(char *context
)
581 if (strcasecmp(context
, "ALL") == 0) return ALL_LOGGERS
;
582 else if (strcasecmp(context
, "PARSR") == 0) return PARSER
;
583 else if (strcasecmp(context
, "GNRAT") == 0) return GENERATOR
;
584 else if (strcasecmp(context
, "IKESA") == 0) return IKE_SA
;
585 else if (strcasecmp(context
, "SAMGR") == 0) return IKE_SA_MANAGER
;
586 else if (strcasecmp(context
, "CHDSA") == 0) return CHILD_SA
;
587 else if (strcasecmp(context
, "MESSG") == 0) return MESSAGE
;
588 else if (strcasecmp(context
, "TPOOL") == 0) return THREAD_POOL
;
589 else if (strcasecmp(context
, "WORKR") == 0) return WORKER
;
590 else if (strcasecmp(context
, "SCHED") == 0) return SCHEDULER
;
591 else if (strcasecmp(context
, "SENDR") == 0) return SENDER
;
592 else if (strcasecmp(context
, "RECVR") == 0) return RECEIVER
;
593 else if (strcasecmp(context
, "SOCKT") == 0) return SOCKET
;
594 else if (strcasecmp(context
, "TESTR") == 0) return TESTER
;
595 else if (strcasecmp(context
, "DAEMN") == 0) return DAEMON
;
596 else if (strcasecmp(context
, "CONFG") == 0) return CONFIG
;
597 else if (strcasecmp(context
, "ENCPL") == 0) return ENCRYPTION_PAYLOAD
;
598 else if (strcasecmp(context
, "PAYLD") == 0) return PAYLOAD
;
603 * set the type of logged messages in a context
605 static void stroke_logtype(private_stroke_t
*this, stroke_msg_t
*msg
)
607 pop_string(msg
, &(msg
->logtype
.context
));
608 pop_string(msg
, &(msg
->logtype
.type
));
610 this->logger
->log(this->logger
, CONTROL
, "received stroke: logtype for %s", msg
->logtype
.context
);
613 logger_context_t context
= get_context(msg
->logtype
.context
);
616 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid context (%s)!", msg
->logtype
.context
);
620 if (strcasecmp(msg
->logtype
.type
, "CONTROL") == 0) level
= CONTROL
;
621 else if (strcasecmp(msg
->logtype
.type
, "ERROR") == 0) level
= ERROR
;
622 else if (strcasecmp(msg
->logtype
.type
, "AUDIT") == 0) level
= AUDIT
;
623 else if (strcasecmp(msg
->logtype
.type
, "RAW") == 0) level
= RAW
;
624 else if (strcasecmp(msg
->logtype
.type
, "PRIVATE") == 0) level
= PRIVATE
;
627 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid type (%s)!", msg
->logtype
.type
);
631 if (msg
->logtype
.enable
)
633 logger_manager
->enable_log_level(logger_manager
, context
, level
);
637 logger_manager
->disable_log_level(logger_manager
, context
, level
);
642 * set the verbosity of a logger
644 static void stroke_loglevel(private_stroke_t
*this, stroke_msg_t
*msg
)
646 pop_string(msg
, &(msg
->loglevel
.context
));
648 this->logger
->log(this->logger
, CONTROL
, "received stroke: loglevel for %s", msg
->loglevel
.context
);
651 logger_context_t context
= get_context(msg
->loglevel
.context
);
655 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid context (%s)!", msg
->loglevel
.context
);
659 if (msg
->loglevel
.level
== 0)
663 else if (msg
->loglevel
.level
== 1)
667 else if (msg
->loglevel
.level
== 2)
671 else if (msg
->loglevel
.level
== 3)
677 this->stroke_logger
->log(this->stroke_logger
, ERROR
, "invalid level (%d)!", msg
->loglevel
.level
);
681 logger_manager
->enable_log_level(logger_manager
, context
, level
);
685 * Implementation of private_stroke_t.stroke_receive.
687 static void stroke_receive(private_stroke_t
*this)
690 u_int16_t msg_length
;
691 struct sockaddr_un strokeaddr
;
692 int strokeaddrlen
= sizeof(strokeaddr
);
698 /* disable cancellation by default */
699 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE
, NULL
);
703 /* wait for connections, but allow thread to terminate */
704 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE
, &oldstate
);
705 strokefd
= accept(this->socket
, (struct sockaddr
*)&strokeaddr
, &strokeaddrlen
);
706 pthread_setcancelstate(oldstate
, NULL
);
710 this->logger
->log(this->logger
, ERROR
, "accepting stroke connection failed: %s", strerror(errno
));
714 /* peek the length */
715 bytes_read
= recv(strokefd
, &msg_length
, sizeof(msg_length
), MSG_PEEK
);
716 if (bytes_read
!= sizeof(msg_length
))
718 this->logger
->log(this->logger
, ERROR
, "reading lenght of stroke message failed");
724 msg
= malloc(msg_length
);
725 bytes_read
= recv(strokefd
, msg
, msg_length
, 0);
726 if (bytes_read
!= msg_length
)
728 this->logger
->log(this->logger
, ERROR
, "reading stroke message failed: %s");
733 strokefile
= fdopen(dup(strokefd
), "w");
734 if (strokefile
== NULL
)
736 this->logger
->log(this->logger
, ERROR
, "opening stroke output channel failed:", strerror(errno
));
742 this->stroke_logger
= logger_create("-", CONTROL
|ERROR
, FALSE
, strokefile
);
744 this->logger
->log_bytes(this->logger
, RAW
, "stroke message", (void*)msg
, msg_length
);
750 stroke_initiate(this, msg
);
755 stroke_terminate(this, msg
);
760 stroke_status(this, msg
);
765 stroke_add_conn(this, msg
);
770 stroke_logtype(this, msg
);
775 stroke_loglevel(this, msg
);
779 this->logger
->log(this->logger
, ERROR
, "received invalid stroke");
781 this->stroke_logger
->destroy(this->stroke_logger
);
789 * Implementation of connection_store_t.get_connection_by_hosts.
791 static connection_t
*get_connection_by_hosts(connection_store_t
*store
, host_t
*my_host
, host_t
*other_host
)
793 private_stroke_t
*this = (private_stroke_t
*)((u_int8_t
*)store
- offsetof(stroke_t
, connections
));
794 iterator_t
*iterator
;
795 connection_t
*found
= NULL
;
797 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "getting config for hosts %s - %s",
798 my_host
->get_address(my_host
), other_host
->get_address(other_host
));
800 iterator
= this->configurations
->create_iterator(this->configurations
,TRUE
);
801 while (iterator
->has_next(iterator
))
803 configuration_entry_t
*entry
;
804 host_t
*config_my_host
, *config_other_host
;
806 iterator
->current(iterator
,(void **) &entry
);
808 config_my_host
= entry
->connection
->get_my_host(entry
->connection
);
809 config_other_host
= entry
->connection
->get_other_host(entry
->connection
);
811 /* first check if ip is equal */
812 if(config_other_host
->ip_equals(config_other_host
, other_host
))
814 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "config entry with remote host %s",
815 config_other_host
->get_address(config_other_host
));
816 /* could be right one, check my_host for default route*/
817 if (config_my_host
->is_default_route(config_my_host
))
819 found
= entry
->connection
->clone(entry
->connection
);
822 /* check now if host informations are the same */
823 else if (config_my_host
->ip_equals(config_my_host
,my_host
))
825 found
= entry
->connection
->clone(entry
->connection
);
830 /* Then check for wildcard hosts!
832 * actually its only checked if other host with default route can be found! */
833 else if (config_other_host
->is_default_route(config_other_host
))
835 /* could be right one, check my_host for default route*/
836 if (config_my_host
->is_default_route(config_my_host
))
838 found
= entry
->connection
->clone(entry
->connection
);
841 /* check now if host informations are the same */
842 else if (config_my_host
->ip_equals(config_my_host
,my_host
))
844 found
= entry
->connection
->clone(entry
->connection
);
849 iterator
->destroy(iterator
);
851 /* apply hosts as they are supplied since my_host may be %defaultroute, and other_host may be %any. */
854 found
->update_my_host(found
, my_host
->clone(my_host
));
855 found
->update_other_host(found
, other_host
->clone(other_host
));
862 * Implementation of connection_store_t.get_connection_by_ids.
864 static connection_t
*get_connection_by_ids(connection_store_t
*store
, identification_t
*my_id
, identification_t
*other_id
)
866 private_stroke_t
*this = (private_stroke_t
*)((u_int8_t
*)store
- offsetof(stroke_t
, connections
));
867 iterator_t
*iterator
;
868 connection_t
*found
= NULL
;
870 this->logger
->log(this->logger
, CONTROL
|LEVEL1
, "getting config for ids %s - %s",
871 my_id
->get_string(my_id
), other_id
->get_string(other_id
));
873 iterator
= this->configurations
->create_iterator(this->configurations
,TRUE
);
874 while (iterator
->has_next(iterator
))
876 configuration_entry_t
*entry
;
877 identification_t
*config_my_id
, *config_other_id
;
879 iterator
->current(iterator
,(void **) &entry
);
881 config_my_id
= entry
->connection
->get_my_id(entry
->connection
);
882 config_other_id
= entry
->connection
->get_other_id(entry
->connection
);
884 /* first check if ids are equal
885 * TODO: Add wildcard checks */
886 if (config_other_id
->equals(config_other_id
, other_id
) &&
887 config_my_id
->equals(config_my_id
, my_id
))
889 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "config entry with remote id %s",
890 config_other_id
->get_string(config_other_id
));
891 found
= entry
->connection
->clone(entry
->connection
);
895 iterator
->destroy(iterator
);
901 * Implementation of private_stroke_t.get_connection_by_name.
903 static connection_t
*get_connection_by_name(private_stroke_t
*this, char *name
)
905 iterator_t
*iterator
;
906 connection_t
*found
= NULL
;
908 iterator
= this->configurations
->create_iterator(this->configurations
, TRUE
);
909 while (iterator
->has_next(iterator
))
911 configuration_entry_t
*entry
;
912 iterator
->current(iterator
,(void **) &entry
);
914 if (strcmp(entry
->name
,name
) == 0)
916 /* found configuration */
917 found
= entry
->connection
;
921 iterator
->destroy(iterator
);
927 * Implementation of policy_store_t.get_policy.
929 static policy_t
*get_policy(policy_store_t
*store
,identification_t
*my_id
, identification_t
*other_id
)
931 private_stroke_t
*this = (private_stroke_t
*)((u_int8_t
*)store
- offsetof(stroke_t
, policies
));
932 iterator_t
*iterator
;
933 policy_t
*found
= NULL
;
935 iterator
= this->configurations
->create_iterator(this->configurations
, TRUE
);
936 while (iterator
->has_next(iterator
))
938 configuration_entry_t
*entry
;
939 iterator
->current(iterator
,(void **) &entry
);
940 identification_t
*config_my_id
= entry
->policy
->get_my_id(entry
->policy
);
941 identification_t
*config_other_id
= entry
->policy
->get_other_id(entry
->policy
);
943 /* check other host first */
944 if (config_other_id
->belongs_to(config_other_id
, other_id
))
946 /* get it if my_id not specified */
949 found
= entry
->policy
->clone(entry
->policy
);
953 if (config_my_id
->belongs_to(config_my_id
, my_id
))
955 found
= entry
->policy
->clone(entry
->policy
);
960 iterator
->destroy(iterator
);
962 /* apply IDs as they are requsted, since they may be configured as %any or such */
967 found
->update_my_id(found
, my_id
->clone(my_id
));
969 found
->update_other_id(found
, other_id
->clone(other_id
));
975 * Implementation of credential_store_t.get_shared_secret.
977 static status_t
get_shared_secret(credential_store_t
*this, identification_t
*identification
, chunk_t
*preshared_secret
)
979 char *secret
= "schluessel\n";
980 preshared_secret
->ptr
= secret
;
981 preshared_secret
->len
= strlen(secret
) + 1;
983 *preshared_secret
= chunk_clone(*preshared_secret
);
988 * Implementation of credential_store_t.get_rsa_public_key.
990 static status_t
get_rsa_public_key(credential_store_t
*store
, identification_t
*identification
, rsa_public_key_t
**public_key
)
992 private_stroke_t
*this = (private_stroke_t
*)((u_int8_t
*)store
- offsetof(stroke_t
, credentials
));
993 iterator_t
*iterator
;
995 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "Looking for public key for %s",
996 identification
->get_string(identification
));
997 iterator
= this->configurations
->create_iterator(this->configurations
, TRUE
);
998 while (iterator
->has_next(iterator
))
1000 configuration_entry_t
*config
;
1001 iterator
->current(iterator
, (void**)&config
);
1002 identification_t
*stored
= config
->policy
->get_other_id(config
->policy
);
1003 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "there is one for %s",
1004 stored
->get_string(stored
));
1005 if (identification
->equals(identification
, stored
))
1007 this->logger
->log(this->logger
, CONTROL
|LEVEL2
, "found a match: %p",
1008 config
->public_key
);
1009 if (config
->public_key
)
1011 iterator
->destroy(iterator
);
1012 *public_key
= config
->public_key
->clone(config
->public_key
);
1017 iterator
->destroy(iterator
);
1022 * Implementation of credential_store_t.get_rsa_private_key.
1024 static status_t
get_rsa_private_key(credential_store_t
*store
, identification_t
*identification
, rsa_private_key_t
**private_key
)
1026 private_stroke_t
*this = (private_stroke_t
*)((u_int8_t
*)store
- offsetof(stroke_t
, credentials
));
1027 iterator_t
*iterator
;
1029 iterator
= this->configurations
->create_iterator(this->configurations
, TRUE
);
1030 while (iterator
->has_next(iterator
))
1032 configuration_entry_t
*config
;
1033 iterator
->current(iterator
, (void**)&config
);
1034 identification_t
*stored
= config
->policy
->get_my_id(config
->policy
);
1035 if (identification
->equals(identification
, stored
))
1037 if (config
->private_key
)
1039 iterator
->destroy(iterator
);
1040 *private_key
= config
->private_key
->clone(config
->private_key
);
1045 iterator
->destroy(iterator
);
1050 * Implementation of stroke_t.destroy.
1052 static void destroy(private_stroke_t
*this)
1054 configuration_entry_t
*entry
;
1055 rsa_private_key_t
*priv_key
;
1057 pthread_cancel(this->assigned_thread
);
1058 pthread_join(this->assigned_thread
, NULL
);
1060 while (this->configurations
->remove_first(this->configurations
, (void **)&entry
) == SUCCESS
)
1062 entry
->destroy(entry
);
1064 this->configurations
->destroy(this->configurations
);
1066 while (this->private_keys
->remove_first(this->private_keys
, (void **)&priv_key
) == SUCCESS
)
1068 priv_key
->destroy(priv_key
);
1070 this->private_keys
->destroy(this->private_keys
);
1072 close(this->socket
);
1073 unlink(socket_addr
.sun_path
);
1078 * Dummy function which does nothing.
1079 * Used for connection_store_t.destroy and policy_store_t.destroy,
1080 * since destruction is done in store_t's destructor...
1082 void do_nothing(void *nothing
)
1088 * Described in header-file
1090 stroke_t
*stroke_create()
1092 private_stroke_t
*this = malloc_thing(private_stroke_t
);
1095 /* public functions */
1096 this->public.connections
.get_connection_by_ids
= get_connection_by_ids
;
1097 this->public.connections
.get_connection_by_hosts
= get_connection_by_hosts
;
1098 this->public.connections
.destroy
= (void (*) (connection_store_t
*))do_nothing
;
1099 this->public.policies
.get_policy
= get_policy
;
1100 this->public.policies
.destroy
= (void (*) (policy_store_t
*))do_nothing
;
1101 this->public.credentials
.get_shared_secret
= (status_t (*)(credential_store_t
*,identification_t
*,chunk_t
*))get_shared_secret
;
1102 this->public.credentials
.get_rsa_public_key
= (status_t (*)(credential_store_t
*,identification_t
*,rsa_public_key_t
**))get_rsa_public_key
;
1103 this->public.credentials
.get_rsa_private_key
= (status_t (*)(credential_store_t
*,identification_t
*,rsa_private_key_t
**))get_rsa_private_key
;
1104 this->public.credentials
.destroy
= (void (*) (credential_store_t
*))do_nothing
;
1105 this->public.destroy
= (void (*)(stroke_t
*))destroy
;
1107 /* private functions */
1108 this->stroke_receive
= stroke_receive
;
1109 this->get_connection_by_name
= get_connection_by_name
;
1111 this->logger
= logger_manager
->get_logger(logger_manager
, CONFIG
);
1113 /* set up unix socket */
1114 this->socket
= socket(AF_UNIX
, SOCK_STREAM
, 0);
1115 if (this->socket
== -1)
1117 this->logger
->log(this->logger
, ERROR
, "could not create whack socket");
1122 old
= umask(~S_IRWXU
);
1123 if (bind(this->socket
, (struct sockaddr
*)&socket_addr
, sizeof(socket_addr
)) < 0)
1125 this->logger
->log(this->logger
, ERROR
, "could not bind stroke socket: %s", strerror(errno
));
1126 close(this->socket
);
1132 if (listen(this->socket
, 0) < 0)
1134 this->logger
->log(this->logger
, ERROR
, "could not listen on stroke socket: %s", strerror(errno
));
1135 close(this->socket
);
1136 unlink(socket_addr
.sun_path
);
1141 /* start a thread reading from the socket */
1142 if (pthread_create(&(this->assigned_thread
), NULL
, (void*(*)(void*))this->stroke_receive
, this) != 0)
1144 this->logger
->log(this->logger
, ERROR
, "Could not spawn stroke thread");
1145 close(this->socket
);
1146 unlink(socket_addr
.sun_path
);
1151 /* private variables */
1152 this->configurations
= linked_list_create();
1153 this->private_keys
= linked_list_create();
1155 load_private_keys(this);
1157 return (&this->public);