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>