Annotation of embedaddon/strongswan/src/pt-tls-client/pt-tls-client.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2013-2015 Andreas Steffen
        !             3:  * HSR Hochschule fuer Technik Rapperswil
        !             4:  *
        !             5:  * Copyright (C) 2010-2013 Martin Willi
        !             6:  * Copyright (C) 2010-2013 revosec AG
        !             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 <unistd.h>
        !            20: #include <stdio.h>
        !            21: #include <sys/types.h>
        !            22: #include <getopt.h>
        !            23: #include <errno.h>
        !            24: #include <string.h>
        !            25: #include <stdlib.h>
        !            26: #ifdef HAVE_SYSLOG
        !            27: #include <syslog.h>
        !            28: #endif
        !            29: 
        !            30: #include <pt_tls.h>
        !            31: #include <pt_tls_client.h>
        !            32: #include <tnc/tnc.h>
        !            33: #include <tls.h>
        !            34: 
        !            35: #include <library.h>
        !            36: #include <utils/debug.h>
        !            37: #include <credentials/sets/mem_cred.h>
        !            38: #include <utils/optionsfrom.h>
        !            39: 
        !            40: /**
        !            41:  * Print usage information
        !            42:  */
        !            43: static void usage(FILE *out)
        !            44: {
        !            45:        fprintf(out,
        !            46:                "Usage: pt-tls  --connect <hostname|address> [--port <port>]\n"
        !            47:                "              [--certid <hex>|--cert <file>]+ [--keyid <hex>|--key <file>]\n"
        !            48:                "              [--key-type rsa|ecdsa] [--client <client-id>]\n"
        !            49:                "              [--secret <password>] [--mutual] [--quiet]\n"
        !            50:                "              [--debug <level>] [--options <filename>]\n");
        !            51: }
        !            52: 
        !            53: /**
        !            54:  * Client routine
        !            55:  */
        !            56: static int client(char *address, uint16_t port, char *identity)
        !            57: {
        !            58:        pt_tls_client_t *assessment;
        !            59:        tls_t *tnccs;
        !            60:        identification_t *server_id, *client_id;
        !            61:        host_t *server_ip, *client_ip;
        !            62:        status_t status;
        !            63: 
        !            64:        server_ip = host_create_from_dns(address, AF_UNSPEC, port);
        !            65:        if (!server_ip)
        !            66:        {
        !            67:                return 1;
        !            68:        }
        !            69: 
        !            70:        client_ip = host_create_any(server_ip->get_family(server_ip));
        !            71:        if (!client_ip)
        !            72:        {
        !            73:                server_ip->destroy(server_ip);
        !            74:                return 1;
        !            75:        }
        !            76:        server_id = identification_create_from_string(address);
        !            77:        client_id = identification_create_from_string(identity);
        !            78: 
        !            79:        tnccs = (tls_t*)tnc->tnccs->create_instance(tnc->tnccs, TNCCS_2_0, FALSE,
        !            80:                                                                server_id, client_id, server_ip, client_ip,
        !            81:                                                                TNC_IFT_TLS_2_0, NULL);
        !            82:        client_ip->destroy(client_ip);
        !            83: 
        !            84:        if (!tnccs)
        !            85:        {
        !            86:                fprintf(stderr, "loading TNCCS failed: %s\n", PLUGINS);
        !            87:                server_ip->destroy(server_ip);
        !            88:                server_id->destroy(server_id);
        !            89:                client_id->destroy(client_id);
        !            90:                return 1;
        !            91:        }
        !            92:        assessment = pt_tls_client_create(server_ip, server_id, client_id);
        !            93:        status = assessment->run_assessment(assessment, (tnccs_t*)tnccs);
        !            94:        assessment->destroy(assessment);
        !            95:        tnccs->destroy(tnccs);
        !            96: 
        !            97:        return (status != SUCCESS);
        !            98: }
        !            99: 
        !           100: 
        !           101: /**
        !           102:  * In-Memory credential set
        !           103:  */
        !           104: static mem_cred_t *creds;
        !           105: 
        !           106: /**
        !           107:  * Load certificate from file
        !           108:  */
        !           109: static bool load_certificate(char *certid, char *filename)
        !           110: {
        !           111:        certificate_t *cert;
        !           112:        chunk_t chunk;
        !           113: 
        !           114:        if (certid)
        !           115:        {
        !           116:                chunk = chunk_from_hex(chunk_create(certid, strlen(certid)), NULL);
        !           117:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
        !           118:                                                                  BUILD_PKCS11_KEYID, chunk, BUILD_END);
        !           119:        }
        !           120:        else
        !           121:        {
        !           122:                cert = lib->creds->create(lib->creds, CRED_CERTIFICATE, CERT_X509,
        !           123:                                                                  BUILD_FROM_FILE, filename, BUILD_END);
        !           124:        }
        !           125:        if (!cert)
        !           126:        {
        !           127:                DBG1(DBG_TLS, "loading certificate from '%s' failed",
        !           128:                                           certid ? certid : filename);
        !           129:                return FALSE;
        !           130:        }
        !           131:        creds->add_cert(creds, TRUE, cert);
        !           132:        return TRUE;
        !           133: }
        !           134: 
        !           135: /**
        !           136:  * Load private key from file
        !           137:  */
        !           138: static bool load_key(char *keyid, char *filename, key_type_t type)
        !           139: {
        !           140:        private_key_t *key;
        !           141:        chunk_t chunk;
        !           142: 
        !           143:        if (keyid)
        !           144:        {
        !           145:                chunk = chunk_from_hex(chunk_create(keyid, strlen(keyid)), NULL);
        !           146:                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, KEY_ANY,
        !           147:                                                                 BUILD_PKCS11_KEYID, chunk, BUILD_END);
        !           148:                chunk_free(&chunk);
        !           149:        }
        !           150:        else
        !           151:        {
        !           152:                key = lib->creds->create(lib->creds, CRED_PRIVATE_KEY, type,
        !           153:                                                                 BUILD_FROM_FILE, filename, BUILD_END);
        !           154:        }
        !           155:        if (!key)
        !           156:        {
        !           157:                DBG1(DBG_TLS, "loading key from '%s' failed", keyid ? keyid : filename);
        !           158:                return FALSE;
        !           159:        }
        !           160:        creds->add_key(creds, key);
        !           161:        return TRUE;
        !           162: }
        !           163: 
        !           164: /**
        !           165:  * Logging and debug level
        !           166:  */
        !           167: static bool log_to_stderr = TRUE;
        !           168: #ifdef HAVE_SYSLOG
        !           169: static bool log_to_syslog = TRUE;
        !           170: #endif /* HAVE_SYSLOG */
        !           171: static level_t default_loglevel = 1;
        !           172: 
        !           173: static void dbg_pt_tls(debug_t group, level_t level, char *fmt, ...)
        !           174: {
        !           175:        va_list args;
        !           176: 
        !           177:        if (level <= default_loglevel)
        !           178:        {
        !           179:                if (log_to_stderr)
        !           180:                {
        !           181:                        va_start(args, fmt);
        !           182:                        vfprintf(stderr, fmt, args);
        !           183:                        va_end(args);
        !           184:                        fprintf(stderr, "\n");
        !           185:                }
        !           186: #ifdef HAVE_SYSLOG
        !           187:                if (log_to_syslog)
        !           188:                {
        !           189:                        char buffer[8192];
        !           190:                        char *current = buffer, *next;
        !           191: 
        !           192:                        /* write in memory buffer first */
        !           193:                        va_start(args, fmt);
        !           194:                        vsnprintf(buffer, sizeof(buffer), fmt, args);
        !           195:                        va_end(args);
        !           196: 
        !           197:                        /* do a syslog with every line */
        !           198:                        while (current)
        !           199:                        {
        !           200:                                next = strchr(current, '\n');
        !           201:                                if (next)
        !           202:                                {
        !           203:                                        *(next++) = '\0';
        !           204:                                }
        !           205:                                syslog(LOG_INFO, "%s\n", current);
        !           206:                                current = next;
        !           207:                        }
        !           208:                }
        !           209: #endif /* HAVE_SYSLOG */
        !           210:        }
        !           211: }
        !           212: 
        !           213: /**
        !           214:  * Initialize logging to stderr/syslog
        !           215:  */
        !           216: static void init_log(const char *program)
        !           217: {
        !           218:        dbg = dbg_pt_tls;
        !           219: 
        !           220:        if (log_to_stderr)
        !           221:        {
        !           222:                setbuf(stderr, NULL);
        !           223:        }
        !           224: #ifdef HAVE_SYSLOG
        !           225:        if (log_to_syslog)
        !           226:        {
        !           227:                openlog(program, LOG_CONS | LOG_NDELAY | LOG_PID, LOG_AUTHPRIV);
        !           228:        }
        !           229: #endif /* HAVE_SYSLOG */
        !           230: }
        !           231: 
        !           232: /**
        !           233:  * Handles --optionsfrom arguments
        !           234:  */
        !           235: options_t *options;
        !           236: 
        !           237: /**
        !           238:  * Cleanup
        !           239:  */
        !           240: static void cleanup()
        !           241: {
        !           242:        lib->processor->cancel(lib->processor);
        !           243:        lib->credmgr->remove_set(lib->credmgr, &creds->set);
        !           244:        creds->destroy(creds);
        !           245:        options->destroy(options);
        !           246:        libtnccs_deinit();
        !           247:        library_deinit();
        !           248: }
        !           249: 
        !           250: /**
        !           251:  * Initialize library
        !           252:  */
        !           253: static void init()
        !           254: {
        !           255:        plugin_feature_t features[] = {
        !           256:                PLUGIN_NOOP,
        !           257:                        PLUGIN_PROVIDE(CUSTOM, "pt-tls-client"),
        !           258:                                PLUGIN_DEPENDS(CUSTOM, "tnccs-manager"),
        !           259:        };
        !           260:        library_init(NULL, "pt-tls-client");
        !           261:        libtnccs_init();
        !           262: 
        !           263:        init_log("pt-tls-client");
        !           264:        options = options_create();
        !           265: 
        !           266:        lib->plugins->add_static_features(lib->plugins, "pt-tls-client", features,
        !           267:                                                                          countof(features), TRUE, NULL, NULL);
        !           268:        if (!lib->plugins->load(lib->plugins,
        !           269:                        lib->settings->get_str(lib->settings, "pt-tls-client.load", PLUGINS)))
        !           270:        {
        !           271:                exit(SS_RC_INITIALIZATION_FAILED);
        !           272:        }
        !           273:        lib->plugins->status(lib->plugins, LEVEL_CTRL);
        !           274: 
        !           275:        creds = mem_cred_create();
        !           276:        lib->credmgr->add_set(lib->credmgr, &creds->set);
        !           277: 
        !           278:        atexit(cleanup);
        !           279: }
        !           280: 
        !           281: int main(int argc, char *argv[])
        !           282: {
        !           283:        char *address = NULL, *identity = "%any", *secret = NULL;
        !           284:        char *keyid = NULL, *key_file = NULL;
        !           285:        key_type_t key_type = KEY_RSA;
        !           286:        int port = PT_TLS_PORT;
        !           287: 
        !           288:        init();
        !           289: 
        !           290:        while (TRUE)
        !           291:        {
        !           292:                struct option long_opts[] = {
        !           293:                        {"help",                no_argument,                    NULL,           'h' },
        !           294:                        {"connect",             required_argument,              NULL,           'c' },
        !           295:                        {"client",              required_argument,              NULL,           'i' },
        !           296:                        {"secret",              required_argument,              NULL,           's' },
        !           297:                        {"port",                required_argument,              NULL,           'p' },
        !           298:                        {"certid",              required_argument,              NULL,           'X' },
        !           299:                        {"cert",                required_argument,              NULL,           'x' },
        !           300:                        {"keyid",               required_argument,              NULL,           'K' },
        !           301:                        {"key",                 required_argument,              NULL,           'k' },
        !           302:                        {"key-type",    required_argument,              NULL,           't' },
        !           303:                        {"mutual",              no_argument,                    NULL,           'm' },
        !           304:                        {"quiet",               no_argument,                    NULL,           'q' },
        !           305:                        {"debug",               required_argument,              NULL,           'd' },
        !           306:                        {"options",             required_argument,              NULL,           '+' },
        !           307:                        {"optionsfrom", required_argument,              NULL,           '+' },
        !           308:                        {0,0,0,0 }
        !           309:                };
        !           310:                switch (getopt_long(argc, argv, "hc:i:s:p:x:K:k:t:mqd:+:", long_opts,
        !           311:                            NULL))
        !           312:                {
        !           313:                        case EOF:
        !           314:                                break;
        !           315:                        case 'h':                       /* --help */
        !           316:                                usage(stdout);
        !           317:                                return 0;
        !           318:                        case 'X':                       /* --certid <hex> */
        !           319:                                if (!load_certificate(optarg, NULL))
        !           320:                                {
        !           321:                                        return 1;
        !           322:                                }
        !           323:                                continue;
        !           324:                        case 'x':                       /* --cert <file> */
        !           325:                                if (!load_certificate(NULL, optarg))
        !           326:                                {
        !           327:                                        return 1;
        !           328:                                }
        !           329:                                continue;
        !           330:                        case 'K':                       /* --keyid <hex> */
        !           331:                                keyid = optarg;
        !           332:                                continue;
        !           333:                        case 'k':                       /* --key <file> */
        !           334:                                key_file = optarg;
        !           335:                                continue;
        !           336:                        case 't':                       /* --key-type <type> */
        !           337:                                if (strcaseeq(optarg, "ecdsa"))
        !           338:                                {
        !           339:                                        key_type = KEY_ECDSA;
        !           340:                                }
        !           341:                                else if (strcaseeq(optarg, "rsa"))
        !           342:                                {
        !           343:                                        key_type = KEY_RSA;
        !           344:                                }
        !           345:                                else
        !           346:                                {
        !           347:                                        key_type = KEY_ANY;
        !           348:                                }
        !           349:                                continue;
        !           350:                        case 'c':                       /* --connect <hostname|address> */
        !           351:                                if (address)
        !           352:                                {
        !           353:                                        usage(stderr);
        !           354:                                        return 1;
        !           355:                                }
        !           356:                                address = optarg;
        !           357:                                continue;
        !           358:                        case 'i':                       /* --client <client-id> */
        !           359:                                identity = optarg;
        !           360:                                continue;
        !           361:                        case 's':                       /* --secret <password> */
        !           362:                                secret = optarg;
        !           363:                                continue;
        !           364:                        case 'p':                       /* --port <port> */
        !           365:                                port = atoi(optarg);
        !           366:                                continue;
        !           367:                        case 'm':                       /* --mutual */
        !           368:                                lib->settings->set_bool(lib->settings,
        !           369:                                                                "%s.plugins.tnccs-20.mutual", TRUE, lib->ns);
        !           370:                                continue;
        !           371:                        case 'q':               /* --quiet */
        !           372:                                log_to_stderr = FALSE;
        !           373:                                continue;
        !           374:                        case 'd':                       /* --debug <level> */
        !           375:                                default_loglevel = atoi(optarg);
        !           376:                                continue;
        !           377:                        case '+':                       /* --optionsfrom <filename> */
        !           378:                                if (!options->from(options, optarg, &argc, &argv, optind))
        !           379:                                {
        !           380:                                        return 1;
        !           381:                                }
        !           382:                                continue;
        !           383:                        default:
        !           384:                                usage(stderr);
        !           385:                                return 1;
        !           386:                }
        !           387:                break;
        !           388:        }
        !           389:        if (!address)
        !           390:        {
        !           391:                usage(stderr);
        !           392:                return 1;
        !           393:        }
        !           394:        if ((keyid || key_file) && !load_key(keyid, key_file, key_type))
        !           395:        {
        !           396:                return 1;
        !           397:        }
        !           398:        if (secret)
        !           399:        {
        !           400:                creds->add_shared(creds, shared_key_create(SHARED_EAP,
        !           401:                                                                                chunk_clone(chunk_from_str(secret))),
        !           402:                                                        identification_create_from_string(identity), NULL);
        !           403:        }
        !           404:        return client(address, port, identity);
        !           405: }

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