Annotation of embedaddon/strongswan/src/charon-nm/nm/nm_service.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2017 Lubomir Rintel
        !             3:  *
        !             4:  * Copyright (C) 2013-2020 Tobias Brunner
        !             5:  * Copyright (C) 2008-2009 Martin Willi
        !             6:  * HSR Hochschule fuer Technik Rapperswil
        !             7:  *
        !             8:  * This program is free software; you can redistribute it and/or modify it
        !             9:  * under the terms of the GNU General Public License as published by the
        !            10:  * Free Software Foundation; either version 2 of the License, or (at your
        !            11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
        !            12:  *
        !            13:  * This program is distributed in the hope that it will be useful, but
        !            14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        !            15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
        !            16:  * for more details.
        !            17:  */
        !            18: 
        !            19: #include "nm_service.h"
        !            20: 
        !            21: #include <daemon.h>
        !            22: #include <networking/host.h>
        !            23: #include <utils/identification.h>
        !            24: #include <config/peer_cfg.h>
        !            25: #include <credentials/certificates/x509.h>
        !            26: 
        !            27: #include <stdio.h>
        !            28: 
        !            29: /**
        !            30:  * Private data of NMStrongswanPlugin
        !            31:  */
        !            32: typedef struct {
        !            33:        /* implements bus listener interface */
        !            34:        listener_t listener;
        !            35:        /* IKE_SA we are listening on */
        !            36:        ike_sa_t *ike_sa;
        !            37:        /* backref to public plugin */
        !            38:        NMVpnServicePlugin *plugin;
        !            39:        /* credentials to use for authentication */
        !            40:        nm_creds_t *creds;
        !            41:        /* attribute handler for DNS/NBNS server information */
        !            42:        nm_handler_t *handler;
        !            43:        /* name of the connection */
        !            44:        char *name;
        !            45: } NMStrongswanPluginPrivate;
        !            46: 
        !            47: G_DEFINE_TYPE_WITH_PRIVATE(NMStrongswanPlugin, nm_strongswan_plugin, NM_TYPE_VPN_SERVICE_PLUGIN)
        !            48: 
        !            49: #define NM_STRONGSWAN_PLUGIN_GET_PRIVATE(o) \
        !            50:                        ((NMStrongswanPluginPrivate*) \
        !            51:                                nm_strongswan_plugin_get_instance_private (o))
        !            52: 
        !            53: /**
        !            54:  * Convert an address chunk to a GValue
        !            55:  */
        !            56: static GVariant *addr_to_variant(chunk_t addr)
        !            57: {
        !            58:        GVariantBuilder builder;
        !            59:        int i;
        !            60: 
        !            61:        switch (addr.len)
        !            62:        {
        !            63:                case 4:
        !            64:                        return g_variant_new_uint32 (*(uint32_t*)addr.ptr);
        !            65:                case 16:
        !            66:                        g_variant_builder_init (&builder, G_VARIANT_TYPE ("ay"));
        !            67:                        for (i = 0; i < addr.len; i++)
        !            68:                        {
        !            69:                                g_variant_builder_add (&builder, "y", addr.ptr[i]);
        !            70: 
        !            71:                        }
        !            72:                        return g_variant_builder_end (&builder);
        !            73:                default:
        !            74:                        return NULL;
        !            75:        }
        !            76: }
        !            77: 
        !            78: /**
        !            79:  * Convert a host to a GValue
        !            80:  */
        !            81: static GVariant *host_to_variant(host_t *host)
        !            82: {
        !            83:        return addr_to_variant(host->get_address(host));
        !            84: }
        !            85: 
        !            86: /**
        !            87:  * Convert enumerated handler chunks to a GValue
        !            88:  */
        !            89: static GVariant* handler_to_variant(nm_handler_t *handler, char *variant_type,
        !            90:                                                         configuration_attribute_type_t type)
        !            91: {
        !            92:        GVariantBuilder builder;
        !            93:        enumerator_t *enumerator;
        !            94:        chunk_t *chunk;
        !            95: 
        !            96:        g_variant_builder_init (&builder, G_VARIANT_TYPE (variant_type));
        !            97: 
        !            98:        enumerator = handler->create_enumerator(handler, type);
        !            99:        while (enumerator->enumerate(enumerator, &chunk))
        !           100:        {
        !           101:                g_variant_builder_add_value (&builder, addr_to_variant(*chunk));
        !           102:        }
        !           103:        enumerator->destroy(enumerator);
        !           104: 
        !           105:        return g_variant_builder_end (&builder);
        !           106: }
        !           107: 
        !           108: /**
        !           109:  * Signal IP config to NM, set connection as established
        !           110:  */
        !           111: static void signal_ip_config(NMVpnServicePlugin *plugin,
        !           112:                                                         ike_sa_t *ike_sa, child_sa_t *child_sa)
        !           113: {
        !           114:        NMStrongswanPlugin *pub = (NMStrongswanPlugin*)plugin;
        !           115:        NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(pub);
        !           116:        GVariantBuilder builder, ip4builder, ip6builder;
        !           117:        GVariant *ip4config, *ip6config;
        !           118:        enumerator_t *enumerator;
        !           119:        host_t *me, *other, *vip4 = NULL, *vip6 = NULL;
        !           120:        nm_handler_t *handler;
        !           121: 
        !           122:        g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
        !           123:        g_variant_builder_init (&ip4builder, G_VARIANT_TYPE_VARDICT);
        !           124:        g_variant_builder_init (&ip6builder, G_VARIANT_TYPE_VARDICT);
        !           125: 
        !           126:        handler = priv->handler;
        !           127: 
        !           128:        /* NM apparently requires to know the gateway */
        !           129:        other = ike_sa->get_other_host(ike_sa);
        !           130:        g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_EXT_GATEWAY,
        !           131:                               host_to_variant(other));
        !           132: 
        !           133:        /* pass the first virtual IPs we got or use the physical IP */
        !           134:        enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, TRUE);
        !           135:        while (enumerator->enumerate(enumerator, &me))
        !           136:        {
        !           137:                switch (me->get_family(me))
        !           138:                {
        !           139:                        case AF_INET:
        !           140:                                if (!vip4)
        !           141:                                {
        !           142:                                        vip4 = me;
        !           143:                                }
        !           144:                                break;
        !           145:                        case AF_INET6:
        !           146:                                if (!vip6)
        !           147:                                {
        !           148:                                        vip6 = me;
        !           149:                                }
        !           150:                                break;
        !           151:                }
        !           152:        }
        !           153:        enumerator->destroy(enumerator);
        !           154:        if (!vip4 && !vip6)
        !           155:        {
        !           156:                me = ike_sa->get_my_host(ike_sa);
        !           157:                switch (me->get_family(me))
        !           158:                {
        !           159:                        case AF_INET:
        !           160:                                vip4 = me;
        !           161:                                break;
        !           162:                        case AF_INET6:
        !           163:                                vip6 = me;
        !           164:                                break;
        !           165:                }
        !           166:        }
        !           167: 
        !           168:        if (vip4)
        !           169:        {
        !           170:                g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_ADDRESS,
        !           171:                                                           host_to_variant(vip4));
        !           172:                g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_PREFIX,
        !           173:                                                           g_variant_new_uint32 (vip4->get_address(vip4).len * 8));
        !           174: 
        !           175:                /* prevent NM from changing the default route. we set our own route in our
        !           176:                 * own routing table
        !           177:                 */
        !           178:                g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NEVER_DEFAULT,
        !           179:                                                           g_variant_new_boolean (TRUE));
        !           180: 
        !           181:                g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_DNS,
        !           182:                                                           handler_to_variant(handler, "au", INTERNAL_IP4_DNS));
        !           183: 
        !           184:                g_variant_builder_add (&ip4builder, "{sv}", NM_VPN_PLUGIN_IP4_CONFIG_NBNS,
        !           185:                                                           handler_to_variant(handler, "au", INTERNAL_IP4_NBNS));
        !           186:        }
        !           187: 
        !           188:        if (vip6)
        !           189:        {
        !           190:                g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_ADDRESS,
        !           191:                                                           host_to_variant(vip6));
        !           192:                g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_PREFIX,
        !           193:                                                           g_variant_new_uint32 (vip6->get_address(vip6).len * 8));
        !           194:                g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_NEVER_DEFAULT,
        !           195:                                                           g_variant_new_boolean (TRUE));
        !           196:                g_variant_builder_add (&ip6builder, "{sv}", NM_VPN_PLUGIN_IP6_CONFIG_DNS,
        !           197:                                                           handler_to_variant(handler, "aay", INTERNAL_IP6_DNS));
        !           198:                /* NM_VPN_PLUGIN_IP6_CONFIG_NBNS is not defined */
        !           199:        }
        !           200: 
        !           201:        ip4config = g_variant_builder_end (&ip4builder);
        !           202:        if (g_variant_n_children (ip4config))
        !           203:        {
        !           204:                g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP4,
        !           205:                                                           g_variant_new_boolean (TRUE));
        !           206:        }
        !           207:        else
        !           208:        {
        !           209:                g_variant_unref (ip4config);
        !           210:                ip4config = NULL;
        !           211:        }
        !           212: 
        !           213:        ip6config = g_variant_builder_end (&ip6builder);
        !           214:        if (g_variant_n_children (ip6config))
        !           215:        {
        !           216:                g_variant_builder_add (&builder, "{sv}", NM_VPN_PLUGIN_CONFIG_HAS_IP6,
        !           217:                                                           g_variant_new_boolean (TRUE));
        !           218:        }
        !           219:        else
        !           220:        {
        !           221:                g_variant_unref (ip6config);
        !           222:                ip6config = NULL;
        !           223:        }
        !           224: 
        !           225:        handler->reset(handler);
        !           226: 
        !           227:        nm_vpn_service_plugin_set_config (plugin, g_variant_builder_end (&builder));
        !           228:        if (ip4config)
        !           229:        {
        !           230:                nm_vpn_service_plugin_set_ip4_config (plugin, ip4config);
        !           231:        }
        !           232:        if (ip6config)
        !           233:        {
        !           234:                nm_vpn_service_plugin_set_ip6_config (plugin, ip6config);
        !           235:        }
        !           236: }
        !           237: 
        !           238: /**
        !           239:  * signal failure to NM, connecting failed
        !           240:  */
        !           241: static void signal_failure(NMVpnServicePlugin *plugin, NMVpnPluginFailure failure)
        !           242: {
        !           243:        NMStrongswanPlugin *pub = (NMStrongswanPlugin*)plugin;
        !           244:        nm_handler_t *handler = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(pub)->handler;
        !           245: 
        !           246:        handler->reset(handler);
        !           247: 
        !           248:        nm_vpn_service_plugin_failure(plugin, failure);
        !           249: }
        !           250: 
        !           251: METHOD(listener_t, ike_state_change, bool,
        !           252:        NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, ike_sa_state_t state)
        !           253: {
        !           254:        if (this->ike_sa == ike_sa && state == IKE_DESTROYING)
        !           255:        {
        !           256:                signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_LOGIN_FAILED);
        !           257:        }
        !           258:        return TRUE;
        !           259: }
        !           260: 
        !           261: METHOD(listener_t, child_state_change, bool,
        !           262:        NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
        !           263:        child_sa_state_t state)
        !           264: {
        !           265:        if (this->ike_sa == ike_sa && state == CHILD_DESTROYING)
        !           266:        {
        !           267:                signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
        !           268:        }
        !           269:        return TRUE;
        !           270: }
        !           271: 
        !           272: METHOD(listener_t, ike_rekey, bool,
        !           273:        NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new)
        !           274: {
        !           275:        if (this->ike_sa == old)
        !           276:        {       /* follow a rekeyed IKE_SA */
        !           277:                this->ike_sa = new;
        !           278:        }
        !           279:        return TRUE;
        !           280: }
        !           281: 
        !           282: METHOD(listener_t, ike_reestablish_pre, bool,
        !           283:        NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new)
        !           284: {
        !           285:        if (this->ike_sa == old)
        !           286:        {       /* ignore child state changes during redirects etc. (task migration) */
        !           287:                this->listener.child_state_change = NULL;
        !           288:        }
        !           289:        return TRUE;
        !           290: }
        !           291: 
        !           292: METHOD(listener_t, ike_reestablish_post, bool,
        !           293:        NMStrongswanPluginPrivate *this, ike_sa_t *old, ike_sa_t *new,
        !           294:        bool initiated)
        !           295: {
        !           296:        if (this->ike_sa == old && initiated)
        !           297:        {       /* if we get redirected during IKE_AUTH we just migrate to the new SA */
        !           298:                this->ike_sa = new;
        !           299:                /* re-register hooks to detect initiation failures */
        !           300:                this->listener.ike_state_change = _ike_state_change;
        !           301:                this->listener.child_state_change = _child_state_change;
        !           302:        }
        !           303:        return TRUE;
        !           304: }
        !           305: 
        !           306: METHOD(listener_t, child_updown, bool,
        !           307:        NMStrongswanPluginPrivate *this, ike_sa_t *ike_sa, child_sa_t *child_sa,
        !           308:        bool up)
        !           309: {
        !           310:        if (this->ike_sa == ike_sa)
        !           311:        {
        !           312:                if (up)
        !           313:                {       /* disable initiate-failure-detection hooks */
        !           314:                        this->listener.ike_state_change = NULL;
        !           315:                        this->listener.child_state_change = NULL;
        !           316:                        signal_ip_config(this->plugin, ike_sa, child_sa);
        !           317:                }
        !           318:                else
        !           319:                {
        !           320:                        if (ike_sa->has_condition(ike_sa, COND_REAUTHENTICATING))
        !           321:                        {       /* we ignore this during reauthentication */
        !           322:                                return TRUE;
        !           323:                        }
        !           324:                        signal_failure(this->plugin, NM_VPN_PLUGIN_FAILURE_CONNECT_FAILED);
        !           325:                }
        !           326:        }
        !           327:        return TRUE;
        !           328: }
        !           329: 
        !           330: /**
        !           331:  * Find a certificate for which we have a private key on a smartcard
        !           332:  */
        !           333: static identification_t *find_smartcard_key(NMStrongswanPluginPrivate *priv,
        !           334:                                                                                        char *pin)
        !           335: {
        !           336:        enumerator_t *enumerator, *sans;
        !           337:        identification_t *id = NULL;
        !           338:        certificate_t *cert;
        !           339:        x509_t *x509;
        !           340:        private_key_t *key;
        !           341:        chunk_t keyid;
        !           342: 
        !           343:        enumerator = lib->credmgr->create_cert_enumerator(lib->credmgr,
        !           344:                                                                                        CERT_X509, KEY_ANY, NULL, FALSE);
        !           345:        while (enumerator->enumerate(enumerator, &cert))
        !           346:        {
        !           347:                x509 = (x509_t*)cert;
        !           348: 
        !           349:                /* there might be a lot of certificates, filter them by usage */
        !           350:                if ((x509->get_flags(x509) & X509_CLIENT_AUTH) &&
        !           351:                        !(x509->get_flags(x509) & X509_CA))
        !           352:                {
        !           353:                        keyid = x509->get_subjectKeyIdentifier(x509);
        !           354:                        if (keyid.ptr)
        !           355:                        {
        !           356:                                /* try to find a private key by the certificate keyid */
        !           357:                                priv->creds->set_pin(priv->creds, keyid, pin);
        !           358:                                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
        !           359:                                                                KEY_ANY, BUILD_PKCS11_KEYID, keyid, BUILD_END);
        !           360:                                if (key)
        !           361:                                {
        !           362:                                        /* prefer a more convenient subjectAltName */
        !           363:                                        sans = x509->create_subjectAltName_enumerator(x509);
        !           364:                                        if (!sans->enumerate(sans, &id))
        !           365:                                        {
        !           366:                                                id = cert->get_subject(cert);
        !           367:                                        }
        !           368:                                        id = id->clone(id);
        !           369:                                        sans->destroy(sans);
        !           370: 
        !           371:                                        DBG1(DBG_CFG, "using smartcard certificate '%Y'", id);
        !           372:                                        priv->creds->set_cert_and_key(priv->creds,
        !           373:                                                                                                  cert->get_ref(cert), key);
        !           374:                                        break;
        !           375:                                }
        !           376:                        }
        !           377:                }
        !           378:        }
        !           379:        enumerator->destroy(enumerator);
        !           380:        return id;
        !           381: }
        !           382: 
        !           383: /**
        !           384:  * Add a client auth config for certificate authentication
        !           385:  */
        !           386: static bool add_auth_cfg_cert(NMStrongswanPluginPrivate *priv,
        !           387:                                                          NMSettingVpn *vpn, peer_cfg_t *peer_cfg,
        !           388:                                                          GError **err)
        !           389: {
        !           390:        identification_t *id = NULL;
        !           391:        certificate_t *cert = NULL;
        !           392:        auth_cfg_t *auth;
        !           393:        const char *str, *method, *cert_source;
        !           394: 
        !           395:        method = nm_setting_vpn_get_data_item(vpn, "method");
        !           396:        cert_source = nm_setting_vpn_get_data_item(vpn, "cert-source") ?: method;
        !           397: 
        !           398:        if (streq(cert_source, "smartcard"))
        !           399:        {
        !           400:                char *pin;
        !           401: 
        !           402:                pin = (char*)nm_setting_vpn_get_secret(vpn, "password");
        !           403:                if (pin)
        !           404:                {
        !           405:                        id = find_smartcard_key(priv, pin);
        !           406:                }
        !           407:                if (!id)
        !           408:                {
        !           409:                        g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           410:                                                NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           411:                                                "No usable smartcard certificate found.");
        !           412:                        return FALSE;
        !           413:                }
        !           414:        }
        !           415:        /* ... or certificate/private key authentication */
        !           416:        else if ((str = nm_setting_vpn_get_data_item(vpn, "usercert")))
        !           417:        {
        !           418:                public_key_t *public;
        !           419:                private_key_t *private = NULL;
        !           420: 
        !           421:                bool agent = streq(cert_source, "agent");
        !           422: 
        !           423:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
        !           424:                                                                  BUILD_FROM_FILE, str, BUILD_END);
        !           425:                if (!cert)
        !           426:                {
        !           427:                        g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           428:                                                NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           429:                                                "Loading peer certificate failed.");
        !           430:                        return FALSE;
        !           431:                }
        !           432:                /* try agent */
        !           433:                str = nm_setting_vpn_get_secret(vpn, "agent");
        !           434:                if (agent && str)
        !           435:                {
        !           436:                        public = cert->get_public_key(cert);
        !           437:                        if (public)
        !           438:                        {
        !           439:                                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
        !           440:                                                                                         public->get_type(public),
        !           441:                                                                                         BUILD_AGENT_SOCKET, str,
        !           442:                                                                                         BUILD_PUBLIC_KEY, public,
        !           443:                                                                                         BUILD_END);
        !           444:                                public->destroy(public);
        !           445:                        }
        !           446:                        if (!private)
        !           447:                        {
        !           448:                                g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           449:                                                        NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           450:                                                        "Connecting to SSH agent failed.");
        !           451:                        }
        !           452:                }
        !           453:                /* ... or key file */
        !           454:                str = nm_setting_vpn_get_data_item(vpn, "userkey");
        !           455:                if (!agent && str)
        !           456:                {
        !           457:                        char *secret;
        !           458: 
        !           459:                        secret = (char*)nm_setting_vpn_get_secret(vpn, "password");
        !           460:                        if (secret)
        !           461:                        {
        !           462:                                priv->creds->set_key_password(priv->creds, secret);
        !           463:                        }
        !           464:                        private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
        !           465:                                                                        KEY_ANY, BUILD_FROM_FILE, str, BUILD_END);
        !           466:                        if (!private)
        !           467:                        {
        !           468:                                g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           469:                                                        NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           470:                                                        "Loading private key failed.");
        !           471:                        }
        !           472:                }
        !           473:                if (private)
        !           474:                {
        !           475:                        id = cert->get_subject(cert);
        !           476:                        id = id->clone(id);
        !           477:                        priv->creds->set_cert_and_key(priv->creds, cert, private);
        !           478:                }
        !           479:                else
        !           480:                {
        !           481:                        DESTROY_IF(cert);
        !           482:                        return FALSE;
        !           483:                }
        !           484:        }
        !           485:        else
        !           486:        {
        !           487:                g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           488:                                        "Certificate is missing.");
        !           489:                return FALSE;
        !           490:        }
        !           491: 
        !           492:        auth = auth_cfg_create();
        !           493:        if (streq(method, "eap-tls"))
        !           494:        {
        !           495:                auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_EAP);
        !           496:                auth->add(auth, AUTH_RULE_EAP_TYPE, EAP_TLS);
        !           497:                auth->add(auth, AUTH_RULE_AAA_IDENTITY,
        !           498:                                  identification_create_from_string("%any"));
        !           499:        }
        !           500:        else
        !           501:        {
        !           502:                auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           503:        }
        !           504:        if (cert)
        !           505:        {
        !           506:                auth->add(auth, AUTH_RULE_SUBJECT_CERT, cert->get_ref(cert));
        !           507:        }
        !           508:        str = nm_setting_vpn_get_data_item(vpn, "local-identity");
        !           509:        if (str)
        !           510:        {
        !           511:                identification_t *local_id;
        !           512: 
        !           513:                local_id = identification_create_from_string((char*)str);
        !           514:                if (local_id)
        !           515:                {
        !           516:                        id->destroy(id);
        !           517:                        id = local_id;
        !           518:                }
        !           519:        }
        !           520:        auth->add(auth, AUTH_RULE_IDENTITY, id);
        !           521:        peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
        !           522:        return TRUE;
        !           523: }
        !           524: 
        !           525: /**
        !           526:  * Add a client auth config for username/password authentication
        !           527:  */
        !           528: static bool add_auth_cfg_pw(NMStrongswanPluginPrivate *priv,
        !           529:                                                        NMSettingVpn *vpn, peer_cfg_t *peer_cfg,
        !           530:                                                        GError **err)
        !           531: {
        !           532:        identification_t *user = NULL, *id = NULL;
        !           533:        auth_cfg_t *auth;
        !           534:        const char *str, *method;
        !           535: 
        !           536:        method = nm_setting_vpn_get_data_item(vpn, "method");
        !           537: 
        !           538:        str = nm_setting_vpn_get_data_item(vpn, "user");
        !           539:        if (str)
        !           540:        {
        !           541:                user = identification_create_from_string((char*)str);
        !           542:        }
        !           543:        else
        !           544:        {
        !           545:                user = identification_create_from_string("%any");
        !           546:        }
        !           547:        str = nm_setting_vpn_get_data_item(vpn, "local-identity");
        !           548:        if (str)
        !           549:        {
        !           550:                id = identification_create_from_string((char*)str);
        !           551:        }
        !           552:        else
        !           553:        {
        !           554:                id = user->clone(user);
        !           555:        }
        !           556:        str = nm_setting_vpn_get_secret(vpn, "password");
        !           557:        if (streq(method, "psk"))
        !           558:        {
        !           559:                if (strlen(str) < 20)
        !           560:                {
        !           561:                        g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           562:                                                NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           563:                                                "Pre-shared key is too short.");
        !           564:                        user->destroy(user);
        !           565:                        id->destroy(id);
        !           566:                        return FALSE;
        !           567:                }
        !           568:                priv->creds->set_username_password(priv->creds, id, (char*)str);
        !           569:        }
        !           570:        else
        !           571:        {
        !           572:                priv->creds->set_username_password(priv->creds, user, (char*)str);
        !           573:        }
        !           574: 
        !           575:        auth = auth_cfg_create();
        !           576:        auth->add(auth, AUTH_RULE_AUTH_CLASS,
        !           577:                          streq(method, "psk") ? AUTH_CLASS_PSK : AUTH_CLASS_EAP);
        !           578:        /* in case EAP-PEAP or EAP-TTLS is used we currently accept any identity */
        !           579:        auth->add(auth, AUTH_RULE_AAA_IDENTITY,
        !           580:                          identification_create_from_string("%any"));
        !           581:        auth->add(auth, AUTH_RULE_EAP_IDENTITY, user);
        !           582:        auth->add(auth, AUTH_RULE_IDENTITY, id);
        !           583:        peer_cfg->add_auth_cfg(peer_cfg, auth, TRUE);
        !           584:        return TRUE;
        !           585: }
        !           586: 
        !           587: /**
        !           588:  * Connect function called from NM via DBUS
        !           589:  */
        !           590: static gboolean connect_(NMVpnServicePlugin *plugin, NMConnection *connection,
        !           591:                                                 GError **err)
        !           592: {
        !           593:        NMStrongswanPlugin *pub = (NMStrongswanPlugin*)plugin;
        !           594:        NMStrongswanPluginPrivate *priv;
        !           595:        NMSettingConnection *conn;
        !           596:        NMSettingVpn *vpn;
        !           597:        enumerator_t *enumerator;
        !           598:        identification_t *gateway = NULL;
        !           599:        const char *str, *method;
        !           600:        bool virtual, proposal;
        !           601:        proposal_t *prop;
        !           602:        ike_cfg_t *ike_cfg;
        !           603:        peer_cfg_t *peer_cfg;
        !           604:        child_cfg_t *child_cfg;
        !           605:        traffic_selector_t *ts;
        !           606:        ike_sa_t *ike_sa;
        !           607:        auth_cfg_t *auth;
        !           608:        certificate_t *cert = NULL;
        !           609:        x509_t *x509;
        !           610:        bool loose_gateway_id = FALSE;
        !           611:        ike_cfg_create_t ike = {
        !           612:                .version = IKEV2,
        !           613:                .local = "%any",
        !           614:                .local_port = charon->socket->get_port(charon->socket, FALSE),
        !           615:                .remote_port = IKEV2_UDP_PORT,
        !           616:                .fragmentation = FRAGMENTATION_YES,
        !           617:        };
        !           618:        peer_cfg_create_t peer = {
        !           619:                .cert_policy = CERT_SEND_IF_ASKED,
        !           620:                .unique = UNIQUE_REPLACE,
        !           621:                .keyingtries = 1,
        !           622:                .rekey_time = 36000, /* 10h */
        !           623:                .jitter_time = 600, /* 10min */
        !           624:                .over_time = 600, /* 10min */
        !           625:        };
        !           626:        child_cfg_create_t child = {
        !           627:                .lifetime = {
        !           628:                        .time = {
        !           629:                                .life = 10800 /* 3h */,
        !           630:                                .rekey = 10200 /* 2h50min */,
        !           631:                                .jitter = 300 /* 5min */
        !           632:                        },
        !           633:                },
        !           634:                .mode = MODE_TUNNEL,
        !           635:        };
        !           636: 
        !           637:        /**
        !           638:         * Read parameters
        !           639:         */
        !           640:        priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(pub);
        !           641:        conn = NM_SETTING_CONNECTION(nm_connection_get_setting(connection,
        !           642:                                                                                                NM_TYPE_SETTING_CONNECTION));
        !           643:        vpn = NM_SETTING_VPN(nm_connection_get_setting(connection,
        !           644:                                                                                                NM_TYPE_SETTING_VPN));
        !           645:        if (priv->name)
        !           646:        {
        !           647:                free(priv->name);
        !           648:        }
        !           649:        priv->name = strdup(nm_setting_connection_get_id(conn));
        !           650:        DBG1(DBG_CFG, "received initiate for NetworkManager connection %s",
        !           651:                 priv->name);
        !           652:        DBG4(DBG_CFG, "%s",
        !           653:                 nm_setting_to_string(NM_SETTING(vpn)));
        !           654:        ike.remote = (char*)nm_setting_vpn_get_data_item(vpn, "address");
        !           655:        if (!ike.remote || !*ike.remote)
        !           656:        {
        !           657:                g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           658:                                        "Gateway address missing.");
        !           659:                return FALSE;
        !           660:        }
        !           661:        str = nm_setting_vpn_get_data_item(vpn, "server-port");
        !           662:        if (str && strlen(str))
        !           663:        {
        !           664:                ike.remote_port = settings_value_as_int((char*)str, ike.remote_port);
        !           665:        }
        !           666:        str = nm_setting_vpn_get_data_item(vpn, "virtual");
        !           667:        virtual = streq(str, "yes");
        !           668:        str = nm_setting_vpn_get_data_item(vpn, "encap");
        !           669:        ike.force_encap = streq(str, "yes");
        !           670:        str = nm_setting_vpn_get_data_item(vpn, "ipcomp");
        !           671:        child.options |= streq(str, "yes") ? OPT_IPCOMP : 0;
        !           672: 
        !           673:        /**
        !           674:         * Register credentials
        !           675:         */
        !           676:        priv->creds->clear(priv->creds);
        !           677: 
        !           678:        /* gateway/CA cert */
        !           679:        str = nm_setting_vpn_get_data_item(vpn, "certificate");
        !           680:        if (str)
        !           681:        {
        !           682:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
        !           683:                                                                  BUILD_FROM_FILE, str, BUILD_END);
        !           684:                if (!cert)
        !           685:                {
        !           686:                        g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           687:                                                NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           688:                                                "Loading gateway certificate failed.");
        !           689:                        return FALSE;
        !           690:                }
        !           691:                priv->creds->add_certificate(priv->creds, cert);
        !           692:        }
        !           693:        else
        !           694:        {
        !           695:                /* no certificate defined, fall back to system-wide CA certificates */
        !           696:                priv->creds->load_ca_dir(priv->creds, lib->settings->get_str(
        !           697:                                                                 lib->settings, "charon-nm.ca_dir", NM_CA_DIR));
        !           698:        }
        !           699: 
        !           700:        str = nm_setting_vpn_get_data_item(vpn, "remote-identity");
        !           701:        if (str)
        !           702:        {
        !           703:                gateway = identification_create_from_string((char*)str);
        !           704:        }
        !           705:        else if (cert)
        !           706:        {
        !           707:                x509 = (x509_t*)cert;
        !           708:                if (!(x509->get_flags(x509) & X509_CA))
        !           709:                {       /* for server certificates, we use the subject as identity */
        !           710:                        gateway = cert->get_subject(cert);
        !           711:                        gateway = gateway->clone(gateway);
        !           712:                }
        !           713:        }
        !           714:        if (!gateway || gateway->get_type(gateway) == ID_ANY)
        !           715:        {
        !           716:                /* if the user configured a CA certificate (or an invalid identity),
        !           717:                 * we use the IP/hostname of the server */
        !           718:                gateway = identification_create_from_string(ike.remote);
        !           719:                loose_gateway_id = TRUE;
        !           720:        }
        !           721:        DBG1(DBG_CFG, "using gateway identity '%Y'", gateway);
        !           722: 
        !           723:        /**
        !           724:         * Set up configurations
        !           725:         */
        !           726:        ike_cfg = ike_cfg_create(&ike);
        !           727: 
        !           728:        str = nm_setting_vpn_get_data_item(vpn, "proposal");
        !           729:        proposal = streq(str, "yes");
        !           730:        str = nm_setting_vpn_get_data_item(vpn, "ike");
        !           731:        if (proposal && str && strlen(str))
        !           732:        {
        !           733:                enumerator = enumerator_create_token(str, ";", "");
        !           734:                while (enumerator->enumerate(enumerator, &str))
        !           735:                {
        !           736:                        prop = proposal_create_from_string(PROTO_IKE, str);
        !           737:                        if (!prop)
        !           738:                        {
        !           739:                                g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           740:                                                        NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
        !           741:                                                        "Invalid IKE proposal.");
        !           742:                                enumerator->destroy(enumerator);
        !           743:                                ike_cfg->destroy(ike_cfg);
        !           744:                                gateway->destroy(gateway);
        !           745:                                return FALSE;
        !           746:                        }
        !           747:                        ike_cfg->add_proposal(ike_cfg, prop);
        !           748:                }
        !           749:                enumerator->destroy(enumerator);
        !           750:        }
        !           751:        else
        !           752:        {
        !           753:                ike_cfg->add_proposal(ike_cfg, proposal_create_default(PROTO_IKE));
        !           754:                ike_cfg->add_proposal(ike_cfg, proposal_create_default_aead(PROTO_IKE));
        !           755:        }
        !           756: 
        !           757:        peer_cfg = peer_cfg_create(priv->name, ike_cfg, &peer);
        !           758:        if (virtual)
        !           759:        {
        !           760:                peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET));
        !           761:                peer_cfg->add_virtual_ip(peer_cfg, host_create_any(AF_INET6));
        !           762:        }
        !           763: 
        !           764:        method = nm_setting_vpn_get_data_item(vpn, "method");
        !           765:        if (streq(method, "cert") ||
        !           766:                streq(method, "eap-tls") ||
        !           767:                streq(method, "key") ||
        !           768:                streq(method, "agent") ||
        !           769:                streq(method, "smartcard"))
        !           770:        {
        !           771:                if (!add_auth_cfg_cert (priv, vpn, peer_cfg, err))
        !           772:                {
        !           773:                        peer_cfg->destroy(peer_cfg);
        !           774:                        ike_cfg->destroy(ike_cfg);
        !           775:                        gateway->destroy(gateway);
        !           776:                        return FALSE;
        !           777:                }
        !           778:        }
        !           779:        else if (streq(method, "eap") ||
        !           780:                         streq(method, "psk"))
        !           781:        {
        !           782:                if (!add_auth_cfg_pw(priv, vpn, peer_cfg, err))
        !           783:                {
        !           784:                        peer_cfg->destroy(peer_cfg);
        !           785:                        ike_cfg->destroy(ike_cfg);
        !           786:                        gateway->destroy(gateway);
        !           787:                        return FALSE;
        !           788:                }
        !           789:        }
        !           790:        else
        !           791:        {
        !           792:                g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_BAD_ARGUMENTS,
        !           793:                                        "Configuration parameters missing.");
        !           794:                peer_cfg->destroy(peer_cfg);
        !           795:                ike_cfg->destroy(ike_cfg);
        !           796:                gateway->destroy(gateway);
        !           797:                return FALSE;
        !           798:        }
        !           799: 
        !           800:        auth = auth_cfg_create();
        !           801:        if (streq(method, "psk"))
        !           802:        {
        !           803:                auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PSK);
        !           804:        }
        !           805:        else
        !           806:        {
        !           807:                auth->add(auth, AUTH_RULE_AUTH_CLASS, AUTH_CLASS_PUBKEY);
        !           808:        }
        !           809:        auth->add(auth, AUTH_RULE_IDENTITY, gateway);
        !           810:        auth->add(auth, AUTH_RULE_IDENTITY_LOOSE, loose_gateway_id);
        !           811:        peer_cfg->add_auth_cfg(peer_cfg, auth, FALSE);
        !           812: 
        !           813:        child_cfg = child_cfg_create(priv->name, &child);
        !           814:        str = nm_setting_vpn_get_data_item(vpn, "esp");
        !           815:        if (proposal && str && strlen(str))
        !           816:        {
        !           817:                enumerator = enumerator_create_token(str, ";", "");
        !           818:                while (enumerator->enumerate(enumerator, &str))
        !           819:                {
        !           820:                        prop = proposal_create_from_string(PROTO_ESP, str);
        !           821:                        if (!prop)
        !           822:                        {
        !           823:                                g_set_error(err, NM_VPN_PLUGIN_ERROR,
        !           824:                                                        NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
        !           825:                                                        "Invalid ESP proposal.");
        !           826:                                enumerator->destroy(enumerator);
        !           827:                                child_cfg->destroy(child_cfg);
        !           828:                                peer_cfg->destroy(peer_cfg);
        !           829:                                return FALSE;
        !           830:                        }
        !           831:                        child_cfg->add_proposal(child_cfg, prop);
        !           832:                }
        !           833:                enumerator->destroy(enumerator);
        !           834:        }
        !           835:        else
        !           836:        {
        !           837:                child_cfg->add_proposal(child_cfg, proposal_create_default(PROTO_ESP));
        !           838:                child_cfg->add_proposal(child_cfg, proposal_create_default_aead(PROTO_ESP));
        !           839:        }
        !           840:        ts = traffic_selector_create_dynamic(0, 0, 65535);
        !           841:        child_cfg->add_traffic_selector(child_cfg, TRUE, ts);
        !           842:        ts = traffic_selector_create_from_cidr("0.0.0.0/0", 0, 0, 65535);
        !           843:        child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
        !           844:        ts = traffic_selector_create_from_cidr("::/0", 0, 0, 65535);
        !           845:        child_cfg->add_traffic_selector(child_cfg, FALSE, ts);
        !           846:        peer_cfg->add_child_cfg(peer_cfg, child_cfg);
        !           847: 
        !           848:        /**
        !           849:         * Prepare IKE_SA
        !           850:         */
        !           851:        ike_sa = charon->ike_sa_manager->checkout_by_config(charon->ike_sa_manager,
        !           852:                                                                                                                peer_cfg);
        !           853:        if (!ike_sa)
        !           854:        {
        !           855:                peer_cfg->destroy(peer_cfg);
        !           856:                g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
        !           857:                                        "IKE version not supported.");
        !           858:                return FALSE;
        !           859:        }
        !           860:        if (!ike_sa->get_peer_cfg(ike_sa))
        !           861:        {
        !           862:                ike_sa->set_peer_cfg(ike_sa, peer_cfg);
        !           863:        }
        !           864:        peer_cfg->destroy(peer_cfg);
        !           865: 
        !           866:        /**
        !           867:         * Register listener, enable  initiate-failure-detection hooks
        !           868:         */
        !           869:        priv->ike_sa = ike_sa;
        !           870:        priv->listener.ike_state_change = _ike_state_change;
        !           871:        priv->listener.child_state_change = _child_state_change;
        !           872: 
        !           873:        /**
        !           874:         * Initiate
        !           875:         */
        !           876:        child_cfg->get_ref(child_cfg);
        !           877:        if (ike_sa->initiate(ike_sa, child_cfg, 0, NULL, NULL) != SUCCESS)
        !           878:        {
        !           879:                charon->ike_sa_manager->checkin_and_destroy(charon->ike_sa_manager, ike_sa);
        !           880: 
        !           881:                g_set_error(err, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_LAUNCH_FAILED,
        !           882:                                        "Initiating failed.");
        !           883:                return FALSE;
        !           884:        }
        !           885:        charon->ike_sa_manager->checkin(charon->ike_sa_manager, ike_sa);
        !           886:        return TRUE;
        !           887: }
        !           888: 
        !           889: /**
        !           890:  * NeedSecrets called from NM via DBUS
        !           891:  */
        !           892: static gboolean need_secrets(NMVpnServicePlugin *plugin, NMConnection *connection,
        !           893:                                                         const char **setting_name, GError **error)
        !           894: {
        !           895:        NMSettingVpn *settings;
        !           896:        const char *method, *cert_source, *path;
        !           897:        bool need_secret = FALSE;
        !           898: 
        !           899:        settings = NM_SETTING_VPN(nm_connection_get_setting(connection,
        !           900:                                                                                                                NM_TYPE_SETTING_VPN));
        !           901:        method = nm_setting_vpn_get_data_item(settings, "method");
        !           902:        if (method)
        !           903:        {
        !           904:                if (streq(method, "cert") ||
        !           905:                        streq(method, "eap-tls") ||
        !           906:                        streq(method, "key") ||
        !           907:                        streq(method, "agent") ||
        !           908:                        streq(method, "smartcard"))
        !           909:                {
        !           910:                        cert_source = nm_setting_vpn_get_data_item(settings, "cert-source");
        !           911:                        if (!cert_source)
        !           912:                        {
        !           913:                                cert_source = method;
        !           914:                        }
        !           915:                        if (streq(cert_source, "agent"))
        !           916:                        {
        !           917:                                need_secret = !nm_setting_vpn_get_secret(settings, "agent");
        !           918:                        }
        !           919:                        else if (streq(cert_source, "smartcard"))
        !           920:                        {
        !           921:                                need_secret = !nm_setting_vpn_get_secret(settings, "password");
        !           922:                        }
        !           923:                        else
        !           924:                        {
        !           925:                                need_secret = TRUE;
        !           926:                                path = nm_setting_vpn_get_data_item(settings, "userkey");
        !           927:                                if (path)
        !           928:                                {
        !           929:                                        private_key_t *key;
        !           930: 
        !           931:                                        /* try to load/decrypt the private key */
        !           932:                                        key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,
        !           933:                                                                        KEY_ANY, BUILD_FROM_FILE, path, BUILD_END);
        !           934:                                        if (key)
        !           935:                                        {
        !           936:                                                key->destroy(key);
        !           937:                                                need_secret = FALSE;
        !           938:                                        }
        !           939:                                        else if (nm_setting_vpn_get_secret(settings, "password"))
        !           940:                                        {
        !           941:                                                need_secret = FALSE;
        !           942:                                        }
        !           943:                                }
        !           944:                        }
        !           945:                }
        !           946:                else if (streq(method, "eap") ||
        !           947:                                 streq(method, "psk"))
        !           948:                {
        !           949:                        need_secret = !nm_setting_vpn_get_secret(settings, "password");
        !           950:                }
        !           951:        }
        !           952:        *setting_name = NM_SETTING_VPN_SETTING_NAME;
        !           953:        return need_secret;
        !           954: }
        !           955: 
        !           956: /**
        !           957:  * The actual disconnection
        !           958:  */
        !           959: static gboolean do_disconnect(gpointer plugin)
        !           960: {
        !           961:        NMStrongswanPluginPrivate *priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
        !           962:        enumerator_t *enumerator;
        !           963:        ike_sa_t *ike_sa;
        !           964:        u_int id;
        !           965: 
        !           966:        /* our ike_sa pointer might be invalid, lookup sa */
        !           967:        enumerator = charon->controller->create_ike_sa_enumerator(
        !           968:                                                                                                        charon->controller, TRUE);
        !           969:        while (enumerator->enumerate(enumerator, &ike_sa))
        !           970:        {
        !           971:                if (priv->ike_sa == ike_sa)
        !           972:                {
        !           973:                        id = ike_sa->get_unique_id(ike_sa);
        !           974:                        enumerator->destroy(enumerator);
        !           975:                        charon->controller->terminate_ike(charon->controller, id, FALSE,
        !           976:                                                                                          controller_cb_empty, NULL, 0);
        !           977:                        return FALSE;
        !           978:                }
        !           979:        }
        !           980:        enumerator->destroy(enumerator);
        !           981: 
        !           982:        g_debug("Connection not found.");
        !           983:        return FALSE;
        !           984: }
        !           985: 
        !           986: /**
        !           987:  * Disconnect called from NM via DBUS
        !           988:  */
        !           989: static gboolean disconnect(NMVpnServicePlugin *plugin, GError **err)
        !           990: {
        !           991:        /* enqueue the actual disconnection, because we may be called in
        !           992:         * response to a listener_t callback and the SA enumeration would
        !           993:         * possibly deadlock. */
        !           994:        g_idle_add(do_disconnect, plugin);
        !           995: 
        !           996:        return TRUE;
        !           997: }
        !           998: 
        !           999: /**
        !          1000:  * Initializer
        !          1001:  */
        !          1002: static void nm_strongswan_plugin_init(NMStrongswanPlugin *plugin)
        !          1003: {
        !          1004:        NMStrongswanPluginPrivate *priv;
        !          1005: 
        !          1006:        priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
        !          1007:        priv->plugin = NM_VPN_SERVICE_PLUGIN(plugin);
        !          1008:        memset(&priv->listener, 0, sizeof(listener_t));
        !          1009:        priv->listener.child_updown = _child_updown;
        !          1010:        priv->listener.ike_rekey = _ike_rekey;
        !          1011:        priv->listener.ike_reestablish_pre = _ike_reestablish_pre;
        !          1012:        priv->listener.ike_reestablish_post = _ike_reestablish_post;
        !          1013:        charon->bus->add_listener(charon->bus, &priv->listener);
        !          1014:        priv->name = NULL;
        !          1015: }
        !          1016: 
        !          1017: /**
        !          1018:  * Class constructor
        !          1019:  */
        !          1020: static void nm_strongswan_plugin_class_init(
        !          1021:                                                                        NMStrongswanPluginClass *strongswan_class)
        !          1022: {
        !          1023:        NMVpnServicePluginClass *parent_class = NM_VPN_SERVICE_PLUGIN_CLASS(strongswan_class);
        !          1024: 
        !          1025:        parent_class->connect = connect_;
        !          1026:        parent_class->need_secrets = need_secrets;
        !          1027:        parent_class->disconnect = disconnect;
        !          1028: }
        !          1029: 
        !          1030: /**
        !          1031:  * Object constructor
        !          1032:  */
        !          1033: NMStrongswanPlugin *nm_strongswan_plugin_new(nm_creds_t *creds,
        !          1034:                                                                                         nm_handler_t *handler)
        !          1035: {
        !          1036:        GError *error = NULL;
        !          1037: 
        !          1038:        NMStrongswanPlugin *plugin = (NMStrongswanPlugin *)g_initable_new (
        !          1039:                                        NM_TYPE_STRONGSWAN_PLUGIN,
        !          1040:                                        NULL,
        !          1041:                                        &error,
        !          1042:                                        NM_VPN_SERVICE_PLUGIN_DBUS_SERVICE_NAME, NM_DBUS_SERVICE_STRONGSWAN,
        !          1043:                                        NULL);
        !          1044: 
        !          1045:        if (plugin)
        !          1046:        {
        !          1047:                NMStrongswanPluginPrivate *priv;
        !          1048: 
        !          1049:                /* the rest of the initialization happened in _init above */
        !          1050:                priv = NM_STRONGSWAN_PLUGIN_GET_PRIVATE(plugin);
        !          1051:                priv->creds = creds;
        !          1052:                priv->handler = handler;
        !          1053:        }
        !          1054:        else
        !          1055:        {
        !          1056:                g_warning ("Failed to initialize a plugin instance: %s", error->message);
        !          1057:                g_error_free (error);
        !          1058:        }
        !          1059: 
        !          1060:        return plugin;
        !          1061: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>