Annotation of embedaddon/strongswan/src/pt-tls-client/pt-tls-client.c, revision 1.1.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>