Annotation of embedaddon/strongswan/src/libcharon/plugins/stroke/stroke_socket.c, revision 1.1.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>