Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_socket.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2011-2013 Tobias Brunner
! 3: * Copyright (C) 2008 Martin Willi
! 4: * HSR Hochschule fuer Technik Rapperswil
! 5: *
! 6: * This program is free software; you can redistribute it and/or modify it
! 7: * under the terms of the GNU General Public License as published by the
! 8: * Free Software Foundation; either version 2 of the License, or (at your
! 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
! 10: *
! 11: * This program is distributed in the hope that it will be useful, but
! 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
! 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
! 14: * for more details.
! 15: */
! 16:
! 17: #include "stroke_socket.h"
! 18:
! 19: #include <stdlib.h>
! 20: #include <sys/types.h>
! 21: #include <sys/stat.h>
! 22: #include <sys/socket.h>
! 23: #include <sys/un.h>
! 24: #include <unistd.h>
! 25: #include <errno.h>
! 26:
! 27: #include <daemon.h>
! 28:
! 29: #include "stroke_config.h"
! 30: #include "stroke_control.h"
! 31: #include "stroke_cred.h"
! 32: #include "stroke_ca.h"
! 33: #include "stroke_attribute.h"
! 34: #include "stroke_handler.h"
! 35: #include "stroke_list.h"
! 36: #include "stroke_counter.h"
! 37:
! 38: /**
! 39: * To avoid clogging the thread pool with (blocking) jobs, we limit the number
! 40: * of concurrently handled stroke commands.
! 41: */
! 42: #define MAX_CONCURRENT_DEFAULT 4
! 43:
! 44: typedef struct stroke_job_context_t stroke_job_context_t;
! 45: typedef struct private_stroke_socket_t private_stroke_socket_t;
! 46:
! 47: /**
! 48: * private data of stroke_socket
! 49: */
! 50: struct private_stroke_socket_t {
! 51:
! 52: /**
! 53: * public functions
! 54: */
! 55: stroke_socket_t public;
! 56:
! 57: /**
! 58: * Service accepting stroke connections
! 59: */
! 60: stream_service_t *service;
! 61:
! 62: /**
! 63: * configuration backend
! 64: */
! 65: stroke_config_t *config;
! 66:
! 67: /**
! 68: * attribute provider
! 69: */
! 70: stroke_attribute_t *attribute;
! 71:
! 72: /**
! 73: * attribute handler (requests only)
! 74: */
! 75: stroke_handler_t *handler;
! 76:
! 77: /**
! 78: * controller to control daemon
! 79: */
! 80: stroke_control_t *control;
! 81:
! 82: /**
! 83: * credential set
! 84: */
! 85: stroke_cred_t *cred;
! 86:
! 87: /**
! 88: * CA sections
! 89: */
! 90: stroke_ca_t *ca;
! 91:
! 92: /**
! 93: * status information logging
! 94: */
! 95: stroke_list_t *list;
! 96:
! 97: /**
! 98: * Counter values for IKE events
! 99: */
! 100: stroke_counter_t *counter;
! 101:
! 102: /**
! 103: * TRUE if log level changes are not allowed
! 104: */
! 105: bool prevent_loglevel_changes;
! 106: };
! 107:
! 108: /**
! 109: * Helper macro to log configuration options, but only if they are defined.
! 110: */
! 111: #define DBG_OPT(...) VA_ARGS_DISPATCH(DBG_OPT, __VA_ARGS__)(__VA_ARGS__)
! 112: #define DBG_OPT2(fmt, val) ({ \
! 113: typeof(val) _val = val; \
! 114: if (_val) { DBG2(DBG_CFG, fmt, _val); } \
! 115: })
! 116: #define DBG_OPT3(fmt, label, val) ({ \
! 117: typeof(val) _val = val; \
! 118: if (_val) { DBG2(DBG_CFG, fmt, label, _val); } \
! 119: })
! 120:
! 121: /**
! 122: * Helper function which corrects the string pointers
! 123: * in a stroke_msg_t. Strings in a stroke_msg sent over "wire"
! 124: * contains RELATIVE addresses (relative to the beginning of the
! 125: * stroke_msg). They must be corrected if they reach our address
! 126: * space...
! 127: */
! 128: static void pop_string(stroke_msg_t *msg, char **string)
! 129: {
! 130: if (*string == NULL)
! 131: {
! 132: return;
! 133: }
! 134:
! 135: /* check for sanity of string pointer and string */
! 136: if (string < (char**)msg ||
! 137: string > (char**)((char*)msg + sizeof(stroke_msg_t)) ||
! 138: (unsigned long)*string < (unsigned long)((char*)msg->buffer - (char*)msg) ||
! 139: (unsigned long)*string > msg->length)
! 140: {
! 141: *string = "(invalid pointer in stroke msg)";
! 142: }
! 143: else
! 144: {
! 145: *string = (char*)msg + (unsigned long)*string;
! 146: }
! 147: }
! 148:
! 149: /**
! 150: * Pop the strings of a stroke_end_t struct and log them for debugging purposes
! 151: */
! 152: static void pop_end(stroke_msg_t *msg, const char* label, stroke_end_t *end)
! 153: {
! 154: pop_string(msg, &end->address);
! 155: pop_string(msg, &end->subnets);
! 156: pop_string(msg, &end->sourceip);
! 157: pop_string(msg, &end->dns);
! 158: pop_string(msg, &end->auth);
! 159: pop_string(msg, &end->auth2);
! 160: pop_string(msg, &end->id);
! 161: pop_string(msg, &end->id2);
! 162: pop_string(msg, &end->rsakey);
! 163: pop_string(msg, &end->cert);
! 164: pop_string(msg, &end->cert2);
! 165: pop_string(msg, &end->ca);
! 166: pop_string(msg, &end->ca2);
! 167: pop_string(msg, &end->groups);
! 168: pop_string(msg, &end->groups2);
! 169: pop_string(msg, &end->cert_policy);
! 170: pop_string(msg, &end->updown);
! 171:
! 172: DBG_OPT(" %s=%s", label, end->address);
! 173: DBG_OPT(" %ssubnet=%s", label, end->subnets);
! 174: DBG_OPT(" %ssourceip=%s", label, end->sourceip);
! 175: DBG_OPT(" %sdns=%s", label, end->dns);
! 176: DBG_OPT(" %sauth=%s", label, end->auth);
! 177: DBG_OPT(" %sauth2=%s", label, end->auth2);
! 178: DBG_OPT(" %sid=%s", label, end->id);
! 179: DBG_OPT(" %sid2=%s", label, end->id2);
! 180: DBG_OPT(" %srsakey=%s", label, end->rsakey);
! 181: DBG_OPT(" %scert=%s", label, end->cert);
! 182: DBG_OPT(" %scert2=%s", label, end->cert2);
! 183: DBG_OPT(" %sca=%s", label, end->ca);
! 184: DBG_OPT(" %sca2=%s", label, end->ca2);
! 185: DBG_OPT(" %sgroups=%s", label, end->groups);
! 186: DBG_OPT(" %sgroups2=%s", label, end->groups2);
! 187: DBG_OPT(" %supdown=%s", label, end->updown);
! 188: }
! 189:
! 190: /**
! 191: * Add a connection to the configuration list
! 192: */
! 193: static void stroke_add_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
! 194: {
! 195: pop_string(msg, &msg->add_conn.name);
! 196: DBG1(DBG_CFG, "received stroke: add connection '%s'", msg->add_conn.name);
! 197:
! 198: DBG2(DBG_CFG, "conn %s", msg->add_conn.name);
! 199: pop_end(msg, "left", &msg->add_conn.me);
! 200: pop_end(msg, "right", &msg->add_conn.other);
! 201: pop_string(msg, &msg->add_conn.eap_identity);
! 202: pop_string(msg, &msg->add_conn.aaa_identity);
! 203: pop_string(msg, &msg->add_conn.xauth_identity);
! 204: pop_string(msg, &msg->add_conn.algorithms.ike);
! 205: pop_string(msg, &msg->add_conn.algorithms.esp);
! 206: pop_string(msg, &msg->add_conn.algorithms.ah);
! 207: pop_string(msg, &msg->add_conn.ikeme.mediated_by);
! 208: pop_string(msg, &msg->add_conn.ikeme.peerid);
! 209: DBG_OPT(" eap_identity=%s", msg->add_conn.eap_identity);
! 210: DBG_OPT(" aaa_identity=%s", msg->add_conn.aaa_identity);
! 211: DBG_OPT(" xauth_identity=%s", msg->add_conn.xauth_identity);
! 212: DBG_OPT(" ike=%s", msg->add_conn.algorithms.ike);
! 213: DBG_OPT(" esp=%s", msg->add_conn.algorithms.esp);
! 214: DBG_OPT(" ah=%s", msg->add_conn.algorithms.ah);
! 215: DBG_OPT(" dpddelay=%d", msg->add_conn.dpd.delay);
! 216: DBG_OPT(" dpdtimeout=%d", msg->add_conn.dpd.timeout);
! 217: DBG_OPT(" dpdaction=%d", msg->add_conn.dpd.action);
! 218: DBG_OPT(" closeaction=%d", msg->add_conn.close_action);
! 219: DBG_OPT(" sha256_96=%s", msg->add_conn.sha256_96 ? "yes" : "no");
! 220: DBG_OPT(" mediation=%s", msg->add_conn.ikeme.mediation ? "yes" : "no");
! 221: DBG_OPT(" mediated_by=%s", msg->add_conn.ikeme.mediated_by);
! 222: DBG_OPT(" me_peerid=%s", msg->add_conn.ikeme.peerid);
! 223: DBG_OPT(" keyexchange=ikev%u", msg->add_conn.version);
! 224:
! 225: this->config->add(this->config, msg);
! 226: this->attribute->add_dns(this->attribute, msg);
! 227: this->handler->add_attributes(this->handler, msg);
! 228: }
! 229:
! 230: /**
! 231: * Delete a connection from the list
! 232: */
! 233: static void stroke_del_conn(private_stroke_socket_t *this, stroke_msg_t *msg)
! 234: {
! 235: pop_string(msg, &msg->del_conn.name);
! 236: DBG1(DBG_CFG, "received stroke: delete connection '%s'", msg->del_conn.name);
! 237:
! 238: this->config->del(this->config, msg);
! 239: this->attribute->del_dns(this->attribute, msg);
! 240: this->handler->del_attributes(this->handler, msg);
! 241: }
! 242:
! 243: /**
! 244: * initiate a connection by name
! 245: */
! 246: static void stroke_initiate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
! 247: {
! 248: pop_string(msg, &msg->initiate.name);
! 249: DBG1(DBG_CFG, "received stroke: initiate '%s'", msg->initiate.name);
! 250:
! 251: this->control->initiate(this->control, msg, out);
! 252: }
! 253:
! 254: /**
! 255: * terminate a connection by name
! 256: */
! 257: static void stroke_terminate(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
! 258: {
! 259: pop_string(msg, &msg->terminate.name);
! 260: DBG1(DBG_CFG, "received stroke: terminate '%s'", msg->terminate.name);
! 261:
! 262: this->control->terminate(this->control, msg, out);
! 263: }
! 264:
! 265: /**
! 266: * terminate a connection by peers virtual IP
! 267: */
! 268: static void stroke_terminate_srcip(private_stroke_socket_t *this,
! 269: stroke_msg_t *msg, FILE *out)
! 270: {
! 271: pop_string(msg, &msg->terminate_srcip.start);
! 272: pop_string(msg, &msg->terminate_srcip.end);
! 273: DBG1(DBG_CFG, "received stroke: terminate-srcip %s-%s",
! 274: msg->terminate_srcip.start, msg->terminate_srcip.end);
! 275:
! 276: this->control->terminate_srcip(this->control, msg, out);
! 277: }
! 278:
! 279: /**
! 280: * rekey a connection by name/id
! 281: */
! 282: static void stroke_rekey(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
! 283: {
! 284: pop_string(msg, &msg->terminate.name);
! 285: DBG1(DBG_CFG, "received stroke: rekey '%s'", msg->rekey.name);
! 286:
! 287: this->control->rekey(this->control, msg, out);
! 288: }
! 289:
! 290: /**
! 291: * route a policy (install SPD entries)
! 292: */
! 293: static void stroke_route(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
! 294: {
! 295: pop_string(msg, &msg->route.name);
! 296: DBG1(DBG_CFG, "received stroke: route '%s'", msg->route.name);
! 297:
! 298: this->control->route(this->control, msg, out);
! 299: }
! 300:
! 301: /**
! 302: * unroute a policy
! 303: */
! 304: static void stroke_unroute(private_stroke_socket_t *this, stroke_msg_t *msg, FILE *out)
! 305: {
! 306: pop_string(msg, &msg->terminate.name);
! 307: DBG1(DBG_CFG, "received stroke: unroute '%s'", msg->route.name);
! 308:
! 309: this->control->unroute(this->control, msg, out);
! 310: }
! 311:
! 312: /**
! 313: * Add a ca information record to the cainfo list
! 314: */
! 315: static void stroke_add_ca(private_stroke_socket_t *this,
! 316: stroke_msg_t *msg, FILE *out)
! 317: {
! 318: pop_string(msg, &msg->add_ca.name);
! 319: DBG1(DBG_CFG, "received stroke: add ca '%s'", msg->add_ca.name);
! 320:
! 321: pop_string(msg, &msg->add_ca.cacert);
! 322: pop_string(msg, &msg->add_ca.crluri);
! 323: pop_string(msg, &msg->add_ca.crluri2);
! 324: pop_string(msg, &msg->add_ca.ocspuri);
! 325: pop_string(msg, &msg->add_ca.ocspuri2);
! 326: pop_string(msg, &msg->add_ca.certuribase);
! 327: DBG2(DBG_CFG, "ca %s", msg->add_ca.name);
! 328: DBG_OPT(" cacert=%s", msg->add_ca.cacert);
! 329: DBG_OPT(" crluri=%s", msg->add_ca.crluri);
! 330: DBG_OPT(" crluri2=%s", msg->add_ca.crluri2);
! 331: DBG_OPT(" ocspuri=%s", msg->add_ca.ocspuri);
! 332: DBG_OPT(" ocspuri2=%s", msg->add_ca.ocspuri2);
! 333: DBG_OPT(" certuribase=%s", msg->add_ca.certuribase);
! 334:
! 335: this->ca->add(this->ca, msg);
! 336: }
! 337:
! 338: /**
! 339: * Delete a ca information record from the cainfo list
! 340: */
! 341: static void stroke_del_ca(private_stroke_socket_t *this,
! 342: stroke_msg_t *msg, FILE *out)
! 343: {
! 344: pop_string(msg, &msg->del_ca.name);
! 345: DBG1(DBG_CFG, "received stroke: delete ca '%s'", msg->del_ca.name);
! 346:
! 347: this->ca->del(this->ca, msg);
! 348: }
! 349:
! 350:
! 351: /**
! 352: * show status of daemon
! 353: */
! 354: static void stroke_status(private_stroke_socket_t *this,
! 355: stroke_msg_t *msg, FILE *out, bool all, bool wait)
! 356: {
! 357: pop_string(msg, &(msg->status.name));
! 358:
! 359: this->list->status(this->list, msg, out, all, wait);
! 360: }
! 361:
! 362: /**
! 363: * list various information
! 364: */
! 365: static void stroke_list(private_stroke_socket_t *this, stroke_msg_t *msg,
! 366: FILE *out)
! 367: {
! 368: if (msg->list.flags & LIST_CAINFOS)
! 369: {
! 370: this->ca->list(this->ca, msg, out);
! 371: }
! 372: this->list->list(this->list, msg, out);
! 373: }
! 374:
! 375: /**
! 376: * reread various information
! 377: */
! 378: static void stroke_reread(private_stroke_socket_t *this,
! 379: stroke_msg_t *msg, FILE *out)
! 380: {
! 381: this->cred->reread(this->cred, msg, out);
! 382: }
! 383:
! 384: /**
! 385: * purge various information
! 386: */
! 387: static void stroke_purge(private_stroke_socket_t *this,
! 388: stroke_msg_t *msg, FILE *out)
! 389: {
! 390: if (msg->purge.flags & PURGE_OCSP)
! 391: {
! 392: lib->credmgr->flush_cache(lib->credmgr, CERT_X509_OCSP_RESPONSE);
! 393: }
! 394: if (msg->purge.flags & PURGE_CRLS)
! 395: {
! 396: lib->credmgr->flush_cache(lib->credmgr, CERT_X509_CRL);
! 397: }
! 398: if (msg->purge.flags & PURGE_CERTS)
! 399: {
! 400: lib->credmgr->flush_cache(lib->credmgr, CERT_X509);
! 401: }
! 402: if (msg->purge.flags & PURGE_IKE)
! 403: {
! 404: this->control->purge_ike(this->control, msg, out);
! 405: }
! 406: }
! 407:
! 408: /**
! 409: * Print a certificate in PEM to out
! 410: */
! 411: static void print_pem_cert(FILE *out, certificate_t *cert)
! 412: {
! 413: chunk_t encoded;
! 414:
! 415: if (cert->get_encoding(cert, CERT_PEM, &encoded))
! 416: {
! 417: fprintf(out, "%.*s", (int)encoded.len, encoded.ptr);
! 418: free(encoded.ptr);
! 419: }
! 420: }
! 421:
! 422: /**
! 423: * Export in-memory credentials
! 424: */
! 425: static void stroke_export(private_stroke_socket_t *this,
! 426: stroke_msg_t *msg, FILE *out)
! 427: {
! 428: pop_string(msg, &msg->export.selector);
! 429:
! 430: if (msg->export.flags & EXPORT_X509)
! 431: {
! 432: enumerator_t *enumerator;
! 433: identification_t *id;
! 434: certificate_t *cert;
! 435:
! 436: id = identification_create_from_string(msg->export.selector);
! 437: enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
! 438: CERT_X509, KEY_ANY, id, FALSE);
! 439: while (enumerator->enumerate(enumerator, &cert))
! 440: {
! 441: print_pem_cert(out, cert);
! 442: }
! 443: enumerator->destroy(enumerator);
! 444: id->destroy(id);
! 445: }
! 446:
! 447: if (msg->export.flags & (EXPORT_CONN_CERT | EXPORT_CONN_CHAIN))
! 448: {
! 449: enumerator_t *sas, *auths, *certs;
! 450: ike_sa_t *ike_sa;
! 451: auth_cfg_t *auth;
! 452: certificate_t *cert;
! 453: auth_rule_t rule;
! 454:
! 455: sas = charon->ike_sa_manager->create_enumerator(
! 456: charon->ike_sa_manager, TRUE);
! 457: while (sas->enumerate(sas, &ike_sa))
! 458: {
! 459: if (streq(msg->export.selector, ike_sa->get_name(ike_sa)))
! 460: {
! 461: auths = ike_sa->create_auth_cfg_enumerator(ike_sa, FALSE);
! 462: while (auths->enumerate(auths, &auth))
! 463: {
! 464: bool got_subject = FALSE;
! 465:
! 466: certs = auth->create_enumerator(auth);
! 467: while (certs->enumerate(certs, &rule, &cert))
! 468: {
! 469: switch (rule)
! 470: {
! 471: case AUTH_RULE_CA_CERT:
! 472: case AUTH_RULE_IM_CERT:
! 473: if (msg->export.flags & EXPORT_CONN_CHAIN)
! 474: {
! 475: print_pem_cert(out, cert);
! 476: }
! 477: break;
! 478: case AUTH_RULE_SUBJECT_CERT:
! 479: if (!got_subject)
! 480: {
! 481: print_pem_cert(out, cert);
! 482: got_subject = TRUE;
! 483: }
! 484: break;
! 485: default:
! 486: break;
! 487: }
! 488: }
! 489: certs->destroy(certs);
! 490: }
! 491: auths->destroy(auths);
! 492: }
! 493: }
! 494: sas->destroy(sas);
! 495: }
! 496: }
! 497:
! 498: /**
! 499: * list pool leases
! 500: */
! 501: static void stroke_leases(private_stroke_socket_t *this,
! 502: stroke_msg_t *msg, FILE *out)
! 503: {
! 504: pop_string(msg, &msg->leases.pool);
! 505: pop_string(msg, &msg->leases.address);
! 506:
! 507: this->list->leases(this->list, msg, out);
! 508: }
! 509:
! 510: /**
! 511: * Callback function for usage report
! 512: */
! 513: static void report_usage(FILE *out, int count, size_t bytes,
! 514: backtrace_t *bt, bool detailed)
! 515: {
! 516: fprintf(out, "%zu bytes total, %d allocations, %zu bytes average:\n",
! 517: bytes, count, bytes / count);
! 518: bt->log(bt, out, detailed);
! 519: }
! 520:
! 521: /**
! 522: * Callback function for memusage summary
! 523: */
! 524: static void sum_usage(FILE *out, int count, size_t bytes, int whitelisted)
! 525: {
! 526: fprintf(out, "Total memory usage: %zu\n", bytes);
! 527: }
! 528:
! 529: /**
! 530: * Show memory usage
! 531: */
! 532: static void stroke_memusage(private_stroke_socket_t *this,
! 533: stroke_msg_t *msg, FILE *out)
! 534: {
! 535: if (lib->leak_detective)
! 536: {
! 537: lib->leak_detective->usage(lib->leak_detective,
! 538: (leak_detective_report_cb_t)report_usage,
! 539: (leak_detective_summary_cb_t)sum_usage, out);
! 540: }
! 541: }
! 542:
! 543: /**
! 544: * Set username and password for a connection
! 545: */
! 546: static void stroke_user_creds(private_stroke_socket_t *this,
! 547: stroke_msg_t *msg, FILE *out)
! 548: {
! 549: pop_string(msg, &msg->user_creds.name);
! 550: pop_string(msg, &msg->user_creds.username);
! 551: pop_string(msg, &msg->user_creds.password);
! 552:
! 553: DBG1(DBG_CFG, "received stroke: user-creds '%s'", msg->user_creds.name);
! 554:
! 555: this->config->set_user_credentials(this->config, msg, out);
! 556: }
! 557:
! 558: /**
! 559: * Print stroke counter values
! 560: */
! 561: static void stroke_counters(private_stroke_socket_t *this,
! 562: stroke_msg_t *msg, FILE *out)
! 563: {
! 564: pop_string(msg, &msg->counters.name);
! 565:
! 566: if (msg->counters.reset)
! 567: {
! 568: this->counter->reset(this->counter, msg->counters.name);
! 569: }
! 570: else
! 571: {
! 572: this->counter->print(this->counter, out, msg->counters.name);
! 573: }
! 574: }
! 575:
! 576: /**
! 577: * set the verbosity debug output
! 578: */
! 579: static void stroke_loglevel(private_stroke_socket_t *this,
! 580: stroke_msg_t *msg, FILE *out)
! 581: {
! 582: debug_t group;
! 583:
! 584: pop_string(msg, &(msg->loglevel.type));
! 585: DBG1(DBG_CFG, "received stroke: loglevel %d for %s",
! 586: msg->loglevel.level, msg->loglevel.type);
! 587:
! 588: if (this->prevent_loglevel_changes)
! 589: {
! 590: DBG1(DBG_CFG, "prevented log level change");
! 591: fprintf(out, "command not allowed!\n");
! 592: return;
! 593: }
! 594: if (!enum_from_name(debug_names, msg->loglevel.type, &group))
! 595: {
! 596: fprintf(out, "unknown type '%s'!\n", msg->loglevel.type);
! 597: return;
! 598: }
! 599: charon->set_level(charon, group, msg->loglevel.level);
! 600: }
! 601:
! 602: /**
! 603: * set various config options
! 604: */
! 605: static void stroke_config(private_stroke_socket_t *this,
! 606: stroke_msg_t *msg, FILE *out)
! 607: {
! 608: this->cred->cachecrl(this->cred, msg->config.cachecrl);
! 609: }
! 610:
! 611: /**
! 612: * process a stroke request
! 613: */
! 614: static bool on_accept(private_stroke_socket_t *this, stream_t *stream)
! 615: {
! 616: stroke_msg_t *msg;
! 617: uint16_t len;
! 618: FILE *out;
! 619:
! 620: /* read length */
! 621: if (!stream->read_all(stream, &len, sizeof(len)))
! 622: {
! 623: if (errno != EWOULDBLOCK)
! 624: {
! 625: DBG1(DBG_CFG, "reading length of stroke message failed: %s",
! 626: strerror(errno));
! 627: }
! 628: return FALSE;
! 629: }
! 630: if (len < offsetof(stroke_msg_t, buffer))
! 631: {
! 632: DBG1(DBG_CFG, "invalid stroke message length %d", len);
! 633: return FALSE;
! 634: }
! 635:
! 636: /* read message (we need an additional byte to terminate the buffer) */
! 637: msg = malloc(len + 1);
! 638: msg->length = len;
! 639: if (!stream->read_all(stream, (char*)msg + sizeof(len), len - sizeof(len)))
! 640: {
! 641: if (errno != EWOULDBLOCK)
! 642: {
! 643: DBG1(DBG_CFG, "reading stroke message failed: %s", strerror(errno));
! 644: }
! 645: free(msg);
! 646: return FALSE;
! 647: }
! 648: /* make sure even incorrectly unterminated strings don't extend over the
! 649: * message boundaries */
! 650: ((char*)msg)[len] = '\0';
! 651:
! 652: DBG3(DBG_CFG, "stroke message %b", (void*)msg, len);
! 653:
! 654: out = stream->get_file(stream);
! 655: if (!out)
! 656: {
! 657: DBG1(DBG_CFG, "creating stroke output stream failed");
! 658: free(msg);
! 659: return FALSE;
! 660: }
! 661: switch (msg->type)
! 662: {
! 663: case STR_INITIATE:
! 664: stroke_initiate(this, msg, out);
! 665: break;
! 666: case STR_ROUTE:
! 667: stroke_route(this, msg, out);
! 668: break;
! 669: case STR_UNROUTE:
! 670: stroke_unroute(this, msg, out);
! 671: break;
! 672: case STR_TERMINATE:
! 673: stroke_terminate(this, msg, out);
! 674: break;
! 675: case STR_TERMINATE_SRCIP:
! 676: stroke_terminate_srcip(this, msg, out);
! 677: break;
! 678: case STR_REKEY:
! 679: stroke_rekey(this, msg, out);
! 680: break;
! 681: case STR_STATUS:
! 682: stroke_status(this, msg, out, FALSE, TRUE);
! 683: break;
! 684: case STR_STATUS_ALL:
! 685: stroke_status(this, msg, out, TRUE, TRUE);
! 686: break;
! 687: case STR_STATUS_ALL_NOBLK:
! 688: stroke_status(this, msg, out, TRUE, FALSE);
! 689: break;
! 690: case STR_ADD_CONN:
! 691: stroke_add_conn(this, msg);
! 692: break;
! 693: case STR_DEL_CONN:
! 694: stroke_del_conn(this, msg);
! 695: break;
! 696: case STR_ADD_CA:
! 697: stroke_add_ca(this, msg, out);
! 698: break;
! 699: case STR_DEL_CA:
! 700: stroke_del_ca(this, msg, out);
! 701: break;
! 702: case STR_LOGLEVEL:
! 703: stroke_loglevel(this, msg, out);
! 704: break;
! 705: case STR_CONFIG:
! 706: stroke_config(this, msg, out);
! 707: break;
! 708: case STR_LIST:
! 709: stroke_list(this, msg, out);
! 710: break;
! 711: case STR_REREAD:
! 712: stroke_reread(this, msg, out);
! 713: break;
! 714: case STR_PURGE:
! 715: stroke_purge(this, msg, out);
! 716: break;
! 717: case STR_EXPORT:
! 718: stroke_export(this, msg, out);
! 719: break;
! 720: case STR_LEASES:
! 721: stroke_leases(this, msg, out);
! 722: break;
! 723: case STR_MEMUSAGE:
! 724: stroke_memusage(this, msg, out);
! 725: break;
! 726: case STR_USER_CREDS:
! 727: stroke_user_creds(this, msg, out);
! 728: break;
! 729: case STR_COUNTERS:
! 730: stroke_counters(this, msg, out);
! 731: break;
! 732: default:
! 733: DBG1(DBG_CFG, "received unknown stroke");
! 734: break;
! 735: }
! 736: free(msg);
! 737: fclose(out);
! 738: return FALSE;
! 739: }
! 740:
! 741: METHOD(stroke_socket_t, destroy, void,
! 742: private_stroke_socket_t *this)
! 743: {
! 744: DESTROY_IF(this->service);
! 745: lib->credmgr->remove_set(lib->credmgr, &this->ca->set);
! 746: lib->credmgr->remove_set(lib->credmgr, &this->cred->set);
! 747: charon->backends->remove_backend(charon->backends, &this->config->backend);
! 748: charon->attributes->remove_provider(charon->attributes,
! 749: &this->attribute->provider);
! 750: charon->attributes->remove_handler(charon->attributes,
! 751: &this->handler->handler);
! 752: this->cred->destroy(this->cred);
! 753: this->ca->destroy(this->ca);
! 754: this->config->destroy(this->config);
! 755: this->attribute->destroy(this->attribute);
! 756: this->handler->destroy(this->handler);
! 757: this->control->destroy(this->control);
! 758: this->list->destroy(this->list);
! 759: this->counter->destroy(this->counter);
! 760: free(this);
! 761: }
! 762:
! 763: /*
! 764: * see header file
! 765: */
! 766: stroke_socket_t *stroke_socket_create()
! 767: {
! 768: private_stroke_socket_t *this;
! 769: int max_concurrent;
! 770: char *uri;
! 771:
! 772: INIT(this,
! 773: .public = {
! 774: .destroy = _destroy,
! 775: },
! 776: .prevent_loglevel_changes = lib->settings->get_bool(lib->settings,
! 777: "%s.plugins.stroke.prevent_loglevel_changes", FALSE, lib->ns),
! 778: );
! 779:
! 780: this->ca = stroke_ca_create();
! 781: this->cred = stroke_cred_create(this->ca);
! 782: this->attribute = stroke_attribute_create();
! 783: this->handler = stroke_handler_create();
! 784: this->config = stroke_config_create(this->ca, this->cred, this->attribute);
! 785: this->control = stroke_control_create();
! 786: this->list = stroke_list_create(this->attribute);
! 787: this->counter = stroke_counter_create();
! 788:
! 789: lib->credmgr->add_set(lib->credmgr, &this->ca->set);
! 790: lib->credmgr->add_set(lib->credmgr, &this->cred->set);
! 791: charon->backends->add_backend(charon->backends, &this->config->backend);
! 792: charon->attributes->add_provider(charon->attributes,
! 793: &this->attribute->provider);
! 794: charon->attributes->add_handler(charon->attributes,
! 795: &this->handler->handler);
! 796:
! 797:
! 798: max_concurrent = lib->settings->get_int(lib->settings,
! 799: "%s.plugins.stroke.max_concurrent", MAX_CONCURRENT_DEFAULT,
! 800: lib->ns);
! 801: uri = lib->settings->get_str(lib->settings,
! 802: "%s.plugins.stroke.socket", "unix://" STROKE_SOCKET, lib->ns);
! 803: this->service = lib->streams->create_service(lib->streams, uri, 10);
! 804: if (!this->service)
! 805: {
! 806: DBG1(DBG_CFG, "creating stroke socket failed");
! 807: destroy(this);
! 808: return NULL;
! 809: }
! 810: this->service->on_accept(this->service, (stream_service_cb_t)on_accept,
! 811: this, JOB_PRIO_CRITICAL, max_concurrent);
! 812:
! 813: return &this->public;
! 814: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>