load_end_certificate() now loads certificates
[strongswan.git] / src / charon / threads / stroke_interface.c
1 /**
2 * @file stroke.c
3 *
4 * @brief Implementation of stroke_t.
5 *
6 */
7
8 /*
9 * Copyright (C) 2006 Martin Willi
10 * Hochschule fuer Technik Rapperswil
11 *
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>.
16 *
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
20 * for more details.
21 */
22
23 #include <stdlib.h>
24 #include <sys/types.h>
25 #include <sys/stat.h>
26 #include <sys/socket.h>
27 #include <sys/un.h>
28 #include <sys/fcntl.h>
29 #include <unistd.h>
30 #include <dirent.h>
31 #include <errno.h>
32 #include <pthread.h>
33
34 #include "stroke_interface.h"
35
36 #include <stroke.h>
37 #include <types.h>
38 #include <daemon.h>
39 #include <crypto/x509.h>
40 #include <queues/jobs/initiate_ike_sa_job.h>
41
42 #define IKE_PORT 500
43 #define PATH_BUF 256
44
45 struct sockaddr_un socket_addr = { AF_UNIX, STROKE_SOCKET};
46
47
48 typedef struct private_stroke_t private_stroke_t;
49
50 /**
51 * Private data of an stroke_t object.
52 */
53 struct private_stroke_t {
54
55 /**
56 * Public part of stroke_t object.
57 */
58 stroke_t public;
59
60 /**
61 * Assigned logger_t object in charon.
62 */
63 logger_t *logger;
64
65 /**
66 * Logger which logs to stroke
67 */
68 logger_t *stroke_logger;
69
70 /**
71 * Unix socket to listen for strokes
72 */
73 int socket;
74
75 /**
76 * Thread which reads from the socket
77 */
78 pthread_t assigned_thread;
79
80 /**
81 * Read from the socket and handle stroke messages
82 */
83 void (*stroke_receive) (private_stroke_t *this);
84 };
85
86 /**
87 * Helper function which corrects the string pointers
88 * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
89 * contains RELATIVE addresses (relative to the beginning of the
90 * stroke_msg). They must be corrected if they reach our address
91 * space...
92 */
93 static void pop_string(stroke_msg_t *msg, char **string)
94 {
95 /* check for sanity of string pointer and string */
96 if (*string == NULL)
97 {
98 *string = "";
99 }
100 else if (string < (char**)msg ||
101 string > (char**)msg + sizeof(stroke_msg_t) ||
102 *string < (char*)msg->buffer - (u_int)msg ||
103 *string > (char*)(u_int)msg->length)
104 {
105 *string = "(invalid char* in stroke msg)";
106 }
107 else
108 {
109 *string = (char*)msg + (u_int)*string;
110 }
111 }
112
113 /**
114 * Load end entitity certificate
115 */
116 static void load_end_certificate(const char *filename, identification_t **idp)
117 {
118 char path[PATH_BUF];
119 x509_t *cert;
120
121 if (*filename == '/')
122 {
123 /* absolute path name */
124 snprintf(path, sizeof(path), "%s", filename);
125 }
126 else
127 {
128 /* relative path name */
129 snprintf(path, sizeof(path), "%s/%s", CERTIFICATE_DIR, filename);
130 }
131
132 cert = x509_create_from_file(path);
133
134 if (cert)
135 {
136 identification_t *id = *idp;
137 identification_t *subject = cert->get_subject(cert);
138
139 if (!id->equals(id, subject))
140 {
141 id->destroy(id);
142 id = subject;
143 *idp = id->clone(id);
144 }
145 cert->destroy(cert);
146 }
147 }
148
149 /**
150 * Add a connection to the configuration list
151 */
152 static void stroke_add_conn(private_stroke_t *this, stroke_msg_t *msg)
153 {
154 connection_t *connection;
155 policy_t *policy;
156 identification_t *my_id, *other_id;
157 host_t *my_host, *other_host, *my_subnet, *other_subnet;
158 proposal_t *proposal;
159 traffic_selector_t *my_ts, *other_ts;
160
161 pop_string(msg, &msg->add_conn.name);
162 pop_string(msg, &msg->add_conn.me.address);
163 pop_string(msg, &msg->add_conn.other.address);
164 pop_string(msg, &msg->add_conn.me.id);
165 pop_string(msg, &msg->add_conn.other.id);
166 pop_string(msg, &msg->add_conn.me.cert);
167 pop_string(msg, &msg->add_conn.other.cert);
168 pop_string(msg, &msg->add_conn.me.subnet);
169 pop_string(msg, &msg->add_conn.other.subnet);
170
171 this->logger->log(this->logger, CONTROL, "received stroke: add connection \"%s\"", msg->add_conn.name);
172
173 my_host = host_create(AF_INET, msg->add_conn.me.address, IKE_PORT);
174 if (my_host == NULL)
175 {
176 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.me.address);
177 return;
178 }
179 other_host = host_create(AF_INET, msg->add_conn.other.address, IKE_PORT);
180 if (other_host == NULL)
181 {
182 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid host: %s", msg->add_conn.other.address);
183 my_host->destroy(my_host);
184 return;
185 }
186 my_id = identification_create_from_string(*msg->add_conn.me.id ?
187 msg->add_conn.me.id : msg->add_conn.me.address);
188 if (my_id == NULL)
189 {
190 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.me.id);
191 my_host->destroy(my_host);
192 other_host->destroy(other_host);
193 return;
194 }
195 other_id = identification_create_from_string(*msg->add_conn.other.id ?
196 msg->add_conn.other.id : msg->add_conn.other.address);
197 if (other_id == NULL)
198 {
199 my_host->destroy(my_host);
200 other_host->destroy(other_host);
201 my_id->destroy(my_id);
202 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid id: %s", msg->add_conn.other.id);
203 return;
204 }
205
206 my_subnet = host_create(AF_INET, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet : msg->add_conn.me.address, IKE_PORT);
207 if (my_subnet == NULL)
208 {
209 my_host->destroy(my_host);
210 other_host->destroy(other_host);
211 my_id->destroy(my_id);
212 other_id->destroy(other_id);
213 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet);
214 return;
215 }
216
217 other_subnet = host_create(AF_INET, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet : msg->add_conn.other.address, IKE_PORT);
218 if (other_subnet == NULL)
219 {
220 my_host->destroy(my_host);
221 other_host->destroy(other_host);
222 my_id->destroy(my_id);
223 other_id->destroy(other_id);
224 my_subnet->destroy(my_subnet);
225 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid subnet: %s", msg->add_conn.me.subnet);
226 return;
227 }
228
229 my_ts = traffic_selector_create_from_subnet(my_subnet, *msg->add_conn.me.subnet ? msg->add_conn.me.subnet_mask : 32);
230 my_subnet->destroy(my_subnet);
231 other_ts = traffic_selector_create_from_subnet(other_subnet, *msg->add_conn.other.subnet ? msg->add_conn.other.subnet_mask : 32);
232 other_subnet->destroy(other_subnet);
233
234 if (charon->socket->is_listening_on(charon->socket, other_host))
235 {
236 this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is other host, switching");
237
238 host_t *tmp_host = my_host;
239 identification_t *tmp_id = my_id;
240 traffic_selector_t *tmp_ts = my_ts;
241 char *tmp_cert = msg->add_conn.me.cert;
242
243 my_host = other_host;
244 other_host = tmp_host;
245 my_id = other_id;
246 other_id = tmp_id;
247 my_ts = other_ts;
248 other_ts = tmp_ts;
249 msg->add_conn.me.cert = msg->add_conn.other.cert;
250 msg->add_conn.other.cert = tmp_cert;
251 }
252 else if (charon->socket->is_listening_on(charon->socket, my_host))
253 {
254 this->stroke_logger->log(this->stroke_logger, CONTROL|LEVEL1, "left is own host, not switching");
255 }
256 else
257 {
258 this->stroke_logger->log(this->stroke_logger, ERROR, "left nor right host is our, aborting");
259
260 my_host->destroy(my_host);
261 other_host->destroy(other_host);
262 my_id->destroy(my_id);
263 other_id->destroy(other_id);
264 my_ts->destroy(my_ts);
265 other_ts->destroy(other_ts);
266 return;
267 }
268
269 if (msg->add_conn.me.cert)
270 {
271 load_end_certificate(msg->add_conn.me.cert, &my_id);
272 }
273 if (msg->add_conn.other.cert)
274 {
275 load_end_certificate(msg->add_conn.other.cert, &other_id);
276 }
277
278 connection = connection_create(msg->add_conn.name,
279 my_host, other_host,
280 my_id->clone(my_id), other_id->clone(other_id),
281 RSA_DIGITAL_SIGNATURE);
282 proposal = proposal_create(1);
283 proposal->add_algorithm(proposal, PROTO_IKE, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
284 proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
285 proposal->add_algorithm(proposal, PROTO_IKE, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
286 proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_SHA1, 0);
287 proposal->add_algorithm(proposal, PROTO_IKE, PSEUDO_RANDOM_FUNCTION, PRF_HMAC_MD5, 0);
288 proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_2048_BIT, 0);
289 proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1536_BIT, 0);
290 proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_1024_BIT, 0);
291 proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_4096_BIT, 0);
292 proposal->add_algorithm(proposal, PROTO_IKE, DIFFIE_HELLMAN_GROUP, MODP_8192_BIT, 0);
293 connection->add_proposal(connection, proposal);
294
295 /* add to global connection list */
296 charon->connections->add_connection(charon->connections, connection);
297 this->logger->log(this->logger, CONTROL, "added connection \"%s\": %s[%s]...%s[%s]",
298 msg->add_conn.name,
299 my_host->get_address(my_host),
300 my_id->get_string(my_id),
301 other_host->get_address(other_host),
302 other_id->get_string(other_id));
303
304 policy = policy_create(my_id, other_id);
305 proposal = proposal_create(1);
306 proposal->add_algorithm(proposal, PROTO_ESP, ENCRYPTION_ALGORITHM, ENCR_AES_CBC, 16);
307 proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_SHA1_96, 0);
308 proposal->add_algorithm(proposal, PROTO_ESP, INTEGRITY_ALGORITHM, AUTH_HMAC_MD5_96, 0);
309 policy->add_proposal(policy, proposal);
310 policy->add_my_traffic_selector(policy, my_ts);
311 policy->add_other_traffic_selector(policy, other_ts);
312
313 /* add to global policy list */
314 charon->policies->add_policy(charon->policies, policy);
315
316 }
317
318 /**
319 * initiate a connection by name
320 */
321 static void stroke_initiate(private_stroke_t *this, stroke_msg_t *msg)
322 {
323 initiate_ike_sa_job_t *job;
324 connection_t *connection;
325
326 pop_string(msg, &(msg->initiate.name));
327 this->logger->log(this->logger, CONTROL, "received stroke: initiate \"%s\"", msg->initiate.name);
328 connection = charon->connections->get_connection_by_name(charon->connections, msg->initiate.name);
329 if (connection == NULL)
330 {
331 this->stroke_logger->log(this->stroke_logger, ERROR, "no connection named \"%s\"", msg->initiate.name);
332 }
333 else
334 {
335 job = initiate_ike_sa_job_create(connection);
336 charon->job_queue->add(charon->job_queue, (job_t*)job);
337 }
338 }
339
340 /**
341 * terminate a connection by name
342 */
343 static void stroke_terminate(private_stroke_t *this, stroke_msg_t *msg)
344 {
345 linked_list_t *ike_sas;
346 iterator_t *iterator;
347 int instances = 0;
348
349 pop_string(msg, &(msg->terminate.name));
350 this->logger->log(this->logger, CONTROL, "received stroke: terminate \"%s\"", msg->terminate.name);
351
352 ike_sas = charon->ike_sa_manager->get_ike_sa_list_by_name(charon->ike_sa_manager, msg->terminate.name);
353
354 iterator = ike_sas->create_iterator(ike_sas, TRUE);
355 while (iterator->has_next(iterator))
356 {
357 ike_sa_id_t *ike_sa_id;
358 iterator->current(iterator, (void**)&ike_sa_id);
359 charon->ike_sa_manager->delete(charon->ike_sa_manager, ike_sa_id);
360 ike_sa_id->destroy(ike_sa_id);
361 instances++;
362 }
363 iterator->destroy(iterator);
364 ike_sas->destroy(ike_sas);
365 this->stroke_logger->log(this->stroke_logger, CONTROL, "terminated %d instances of %s", instances, msg->terminate.name);
366 }
367
368 /**
369 * show status of (established) connections
370 */
371 static void stroke_status(private_stroke_t *this, stroke_msg_t *msg)
372 {
373 if (msg->status.name)
374 {
375 pop_string(msg, &(msg->status.name));
376 }
377 charon->ike_sa_manager->log_status(charon->ike_sa_manager, this->stroke_logger, msg->status.name);
378 }
379
380 /**
381 * list various information
382 */
383 static void stroke_list(private_stroke_t *this, stroke_msg_t *msg, bool utc)
384 {
385 if (msg->type = STR_LIST_CERTS)
386 {
387 charon->credentials->log_certificates(charon->credentials, this->stroke_logger, utc);
388 }
389 }
390 logger_context_t get_context(char *context)
391 {
392 if (strcasecmp(context, "ALL") == 0) return ALL_LOGGERS;
393 else if (strcasecmp(context, "PARSR") == 0) return PARSER;
394 else if (strcasecmp(context, "GNRAT") == 0) return GENERATOR;
395 else if (strcasecmp(context, "IKESA") == 0) return IKE_SA;
396 else if (strcasecmp(context, "SAMGR") == 0) return IKE_SA_MANAGER;
397 else if (strcasecmp(context, "CHDSA") == 0) return CHILD_SA;
398 else if (strcasecmp(context, "MESSG") == 0) return MESSAGE;
399 else if (strcasecmp(context, "TPOOL") == 0) return THREAD_POOL;
400 else if (strcasecmp(context, "WORKR") == 0) return WORKER;
401 else if (strcasecmp(context, "SCHED") == 0) return SCHEDULER;
402 else if (strcasecmp(context, "SENDR") == 0) return SENDER;
403 else if (strcasecmp(context, "RECVR") == 0) return RECEIVER;
404 else if (strcasecmp(context, "SOCKT") == 0) return SOCKET;
405 else if (strcasecmp(context, "TESTR") == 0) return TESTER;
406 else if (strcasecmp(context, "DAEMN") == 0) return DAEMON;
407 else if (strcasecmp(context, "CONFG") == 0) return CONFIG;
408 else if (strcasecmp(context, "ENCPL") == 0) return ENCRYPTION_PAYLOAD;
409 else if (strcasecmp(context, "PAYLD") == 0) return PAYLOAD;
410 else return -2;
411 }
412
413 /**
414 * set the type of logged messages in a context
415 */
416 static void stroke_logtype(private_stroke_t *this, stroke_msg_t *msg)
417 {
418 pop_string(msg, &(msg->logtype.context));
419 pop_string(msg, &(msg->logtype.type));
420
421 this->logger->log(this->logger, CONTROL, "received stroke: logtype for %s", msg->logtype.context);
422
423 log_level_t level;
424 logger_context_t context = get_context(msg->logtype.context);
425 if (context == -2)
426 {
427 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->logtype.context);
428 return;
429 }
430
431 if (strcasecmp(msg->logtype.type, "CONTROL") == 0)
432 level = CONTROL;
433 else if (strcasecmp(msg->logtype.type, "ERROR") == 0)
434 level = ERROR;
435 else if (strcasecmp(msg->logtype.type, "AUDIT") == 0)
436 level = AUDIT;
437 else if (strcasecmp(msg->logtype.type, "RAW") == 0)
438 level = RAW;
439 else if (strcasecmp(msg->logtype.type, "PRIVATE") == 0)
440 level = PRIVATE;
441 else
442 {
443 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid type (%s)!", msg->logtype.type);
444 return;
445 }
446
447 if (msg->logtype.enable)
448 {
449 logger_manager->enable_log_level(logger_manager, context, level);
450 }
451 else
452 {
453 logger_manager->disable_log_level(logger_manager, context, level);
454 }
455 }
456
457 /**
458 * set the verbosity of a logger
459 */
460 static void stroke_loglevel(private_stroke_t *this, stroke_msg_t *msg)
461 {
462 log_level_t level;
463 logger_context_t context;
464
465 pop_string(msg, &(msg->loglevel.context));
466 this->logger->log(this->logger, CONTROL, "received stroke: loglevel for %s", msg->loglevel.context);
467
468 context = get_context(msg->loglevel.context);
469 if (context == -2)
470 {
471 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid context (%s)!", msg->loglevel.context);
472 return;
473 }
474
475 if (msg->loglevel.level == 0)
476 level = LEVEL0;
477 else if (msg->loglevel.level == 1)
478 level = LEVEL1;
479 else if (msg->loglevel.level == 2)
480 level = LEVEL2;
481 else if (msg->loglevel.level == 3)
482 level = LEVEL3;
483 else
484 {
485 this->stroke_logger->log(this->stroke_logger, ERROR, "invalid level (%d)!", msg->loglevel.level);
486 return;
487 }
488
489 logger_manager->enable_log_level(logger_manager, context, level);
490 }
491
492 /**
493 * Implementation of private_stroke_t.stroke_receive.
494 */
495 static void stroke_receive(private_stroke_t *this)
496 {
497 stroke_msg_t *msg;
498 u_int16_t msg_length;
499 struct sockaddr_un strokeaddr;
500 int strokeaddrlen = sizeof(strokeaddr);
501 ssize_t bytes_read;
502 int strokefd;
503 FILE *strokefile;
504 int oldstate;
505
506 /* disable cancellation by default */
507 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
508
509 while (1)
510 {
511 /* wait for connections, but allow thread to terminate */
512 pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &oldstate);
513 strokefd = accept(this->socket, (struct sockaddr *)&strokeaddr, &strokeaddrlen);
514 pthread_setcancelstate(oldstate, NULL);
515
516 if (strokefd < 0)
517 {
518 this->logger->log(this->logger, ERROR, "accepting stroke connection failed: %s", strerror(errno));
519 continue;
520 }
521
522 /* peek the length */
523 bytes_read = recv(strokefd, &msg_length, sizeof(msg_length), MSG_PEEK);
524 if (bytes_read != sizeof(msg_length))
525 {
526 this->logger->log(this->logger, ERROR, "reading lenght of stroke message failed");
527 close(strokefd);
528 continue;
529 }
530
531 /* read message */
532 msg = malloc(msg_length);
533 bytes_read = recv(strokefd, msg, msg_length, 0);
534 if (bytes_read != msg_length)
535 {
536 this->logger->log(this->logger, ERROR, "reading stroke message failed: %s");
537 close(strokefd);
538 continue;
539 }
540
541 strokefile = fdopen(dup(strokefd), "w");
542 if (strokefile == NULL)
543 {
544 this->logger->log(this->logger, ERROR, "opening stroke output channel failed:", strerror(errno));
545 close(strokefd);
546 free(msg);
547 continue;
548 }
549
550 /* setup a logger which writes status to the unix socket */
551 this->stroke_logger = logger_create("-", CONTROL|ERROR, FALSE, strokefile);
552
553 this->logger->log_bytes(this->logger, RAW, "stroke message", (void*)msg, msg_length);
554
555 switch (msg->type)
556 {
557 case STR_INITIATE:
558 stroke_initiate(this, msg);
559 break;
560 case STR_TERMINATE:
561 stroke_terminate(this, msg);
562 break;
563 case STR_STATUS:
564 stroke_status(this, msg);
565 break;
566 case STR_STATUS_ALL:
567 this->stroke_logger->enable_level(this->stroke_logger, LEVEL1);
568 stroke_status(this, msg);
569 break;
570 case STR_ADD_CONN:
571 stroke_add_conn(this, msg);
572 break;
573 case STR_LOGTYPE:
574 stroke_logtype(this, msg);
575 break;
576 case STR_LOGLEVEL:
577 stroke_loglevel(this, msg);
578 break;
579 case STR_LIST_CERTS:
580 stroke_list(this, msg, FALSE);
581 break;
582 default:
583 this->logger->log(this->logger, ERROR, "received invalid stroke");
584 }
585 this->stroke_logger->destroy(this->stroke_logger);
586 fclose(strokefile);
587 close(strokefd);
588 free(msg);
589 }
590 }
591
592 /**
593 * Implementation of stroke_t.destroy.
594 */
595 static void destroy(private_stroke_t *this)
596 {
597
598 pthread_cancel(this->assigned_thread);
599 pthread_join(this->assigned_thread, NULL);
600
601 close(this->socket);
602 unlink(socket_addr.sun_path);
603 free(this);
604 }
605
606
607 /*
608 * Described in header-file
609 */
610 stroke_t *stroke_create()
611 {
612 private_stroke_t *this = malloc_thing(private_stroke_t);
613 mode_t old;
614
615 /* public functions */
616 this->public.destroy = (void (*)(stroke_t*))destroy;
617
618 /* private functions */
619 this->stroke_receive = stroke_receive;
620
621 this->logger = logger_manager->get_logger(logger_manager, CONFIG);
622
623 /* set up unix socket */
624 this->socket = socket(AF_UNIX, SOCK_STREAM, 0);
625 if (this->socket == -1)
626 {
627 this->logger->log(this->logger, ERROR, "could not create whack socket");
628 free(this);
629 return NULL;
630 }
631
632 old = umask(~S_IRWXU);
633 if (bind(this->socket, (struct sockaddr *)&socket_addr, sizeof(socket_addr)) < 0)
634 {
635 this->logger->log(this->logger, ERROR, "could not bind stroke socket: %s", strerror(errno));
636 close(this->socket);
637 free(this);
638 return NULL;
639 }
640 umask(old);
641
642 if (listen(this->socket, 0) < 0)
643 {
644 this->logger->log(this->logger, ERROR, "could not listen on stroke socket: %s", strerror(errno));
645 close(this->socket);
646 unlink(socket_addr.sun_path);
647 free(this);
648 return NULL;
649 }
650
651 /* start a thread reading from the socket */
652 if (pthread_create(&(this->assigned_thread), NULL, (void*(*)(void*))this->stroke_receive, this) != 0)
653 {
654 this->logger->log(this->logger, ERROR, "Could not spawn stroke thread");
655 close(this->socket);
656 unlink(socket_addr.sun_path);
657 free(this);
658 return NULL;
659 }
660
661 return (&this->public);
662 }